From bb3777e520ad3e5dc179269ba940c75cab97ec96 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 5 Feb 2026 17:18:27 -0800 Subject: [PATCH 001/100] initial flattenerGeneration test with secretmanager.Secret --- mmv1/products/secretmanager/Secret.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index e113134f5477..62b86082b9bf 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -26,6 +26,7 @@ base_url: 'projects/{{project}}/secrets' self_link: 'projects/{{project}}/secrets/{{secret_id}}' create_url: 'projects/{{project}}/secrets?secretId={{secret_id}}' update_verb: 'PATCH' +flatten_all_in_method: true update_mask: true import_format: - 'projects/{{project}}/secrets/{{secret_id}}' From 1c273c738cdaf18849ac3f0aeba3d483ca324216 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 5 Feb 2026 17:36:51 -0800 Subject: [PATCH 002/100] Decoder generation in flattenerResource test with kms.cryptoKeys --- mmv1/products/kms/CryptoKey.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/kms/CryptoKey.yaml b/mmv1/products/kms/CryptoKey.yaml index 2df23c9526ad..0b9d2d2b966c 100644 --- a/mmv1/products/kms/CryptoKey.yaml +++ b/mmv1/products/kms/CryptoKey.yaml @@ -36,6 +36,7 @@ self_link: '{{key_ring}}/cryptoKeys/{{name}}' create_url: '{{key_ring}}/cryptoKeys?cryptoKeyId={{name}}&skipInitialVersionCreation={{skip_initial_version_creation}}' update_verb: 'PATCH' update_mask: true +flatten_all_in_method: true import_format: - '{{key_ring}}/cryptoKeys/{{name}}' include_in_tgc_next: true From 494b9a0c55a365291e6330e646bdacd49f384678 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 6 Feb 2026 14:09:49 -0800 Subject: [PATCH 003/100] PostRead + NestedQuery in flattenerResource - accesscontextmanager.ServicePerimeterResource --- mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml | 1 + mmv1/products/sql/Database.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml index cecf0c7af172..e9c5adcf9a2a 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml @@ -66,6 +66,7 @@ nested_query: - resources is_list_of_ids: true modify_by_patch: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_resource.go.tmpl' custom_import: 'templates/terraform/custom_import/access_context_manager_service_perimeter_resource.go.tmpl' diff --git a/mmv1/products/sql/Database.yaml b/mmv1/products/sql/Database.yaml index 4f5029b530a4..5aa96e034866 100644 --- a/mmv1/products/sql/Database.yaml +++ b/mmv1/products/sql/Database.yaml @@ -38,6 +38,7 @@ async: result: resource_inside_response: false collection_url_key: 'items' +flatten_all_in_method: true custom_code: pre_read: 'templates/terraform/pre_read/sql_database_activation_policy.tmpl' # Sweeper skipped as this resource has customized deletion. From b573d46eeb0d4a537b2c34d4ada8b131ae14d45a Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 9 Feb 2026 12:59:47 -0800 Subject: [PATCH 004/100] bigquery: flattenResource in dataset --- mmv1/products/bigquery/Dataset.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 5d389755f6c4..698674c9f1c4 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -38,6 +38,8 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true +tgc_include_handwritten_tests: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_dataset.go.tmpl' pre_read: 'templates/terraform/pre_read/bigquery_dataset.go.tmpl' From f8c0498bab05b3d74feab185400d30a795bb975b Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 19 Feb 2026 10:05:45 -0800 Subject: [PATCH 005/100] add flatten_all_in_method on all resources that have a custom_code.decoder set --- .../products/activedirectory/DomainTrust.yaml | 1 + mmv1/products/apigee/DeveloperApp.yaml | 1 + .../apigee/EnvironmentAddonsConfig.yaml | 1 + .../apigee/EnvironmentKeyvaluemaps.yaml | 1 + mmv1/products/apigee/NatAddress.yaml | 1 + mmv1/products/appengine/DomainMapping.yaml | 1 + mmv1/products/backupdr/BackupPlan.yaml | 1 + mmv1/products/bigquery/Dataset.yaml | 1 - .../DataExchangeSubscription.yaml | 1 + .../ListingSubscription.yaml | 1 + .../products/bigquerydatatransfer/Config.yaml | 1 + mmv1/products/cloudasset/FolderFeed.yaml | 1 + .../products/cloudasset/OrganizationFeed.yaml | 1 + mmv1/products/cloudbilling/ProjectInfo.yaml | 6 +- mmv1/products/cloudrun/DomainMapping.yaml | 18 ++++- mmv1/products/cloudrun/Service.yaml | 1 + .../compute/DiskResourcePolicyAttachment.yaml | 1 + .../compute/FirewallPolicyWithRules.yaml | 1 + .../compute/GlobalNetworkEndpoint.yaml | 1 + mmv1/products/compute/Instance.yaml | 1 + mmv1/products/compute/NetworkEndpoint.yaml | 1 + mmv1/products/compute/NetworkEndpoints.yaml | 1 + .../NetworkFirewallPolicyWithRules.yaml | 1 + .../RegionDiskResourcePolicyAttachment.yaml | 69 +++++++++++-------- .../compute/RegionNetworkEndpoint.yaml | 1 + .../RegionNetworkFirewallPolicyWithRules.yaml | 1 + .../compute/ResourcePolicyAttachment.yaml | 65 +++++++++-------- mmv1/products/compute/RouterRoutePolicy.yaml | 1 + mmv1/products/containeranalysis/Note.yaml | 1 + .../containeranalysis/Occurrence.yaml | 1 + mmv1/products/dataplex/Entry.yaml | 1 + mmv1/products/dataproc/Batch.yaml | 1 + mmv1/products/dlp/DeidentifyTemplate.yaml | 1 + mmv1/products/dlp/DiscoveryConfig.yaml | 1 + mmv1/products/dlp/InspectTemplate.yaml | 1 + mmv1/products/dlp/JobTrigger.yaml | 1 + mmv1/products/dlp/StoredInfoType.yaml | 1 + mmv1/products/firebasedatabase/Instance.yaml | 1 + mmv1/products/firestore/Document.yaml | 1 + mmv1/products/healthcare/Dataset.yaml | 1 + mmv1/products/healthcare/DicomStore.yaml | 1 + mmv1/products/healthcare/FhirStore.yaml | 1 + mmv1/products/healthcare/Hl7V2Store.yaml | 1 + mmv1/products/healthcare/PipelineJob.yaml | 1 + .../WorkloadIdentityPoolManagedIdentity.yaml | 1 + .../WorkloadIdentityPoolNamespace.yaml | 1 + .../iambeta/WorkloadIdentityPoolProvider.yaml | 1 + .../iamworkforcepool/OauthClient.yaml | 1 + .../OauthClientCredential.yaml | 1 + .../iamworkforcepool/WorkforcePool.yaml | 1 + .../WorkforcePoolProviderScimTenant.yaml | 1 + .../WorkforcePoolProviderScimToken.yaml | 1 + mmv1/products/integrations/Client.yaml | 1 + mmv1/products/kms/KeyHandle.yaml | 1 + mmv1/products/kms/KeyRing.yaml | 1 + mmv1/products/kms/SecretCiphertext.yaml | 58 +++++++++------- mmv1/products/memorystore/Instance.yaml | 1 + .../products/monitoring/MonitoredProject.yaml | 1 + .../monitoring/NotificationChannel.yaml | 1 + mmv1/products/privateca/CaPool.yaml | 1 + .../privateca/CertificateAuthority.yaml | 1 + mmv1/products/redis/Cluster.yaml | 1 + mmv1/products/redis/Instance.yaml | 1 + mmv1/products/resourcemanager/Lien.yaml | 1 + .../products/secretmanager/SecretVersion.yaml | 1 + .../RegionalSecretVersion.yaml | 1 + mmv1/products/servicedirectory/Endpoint.yaml | 1 + mmv1/products/spanner/BackupSchedule.yaml | 1 + mmv1/products/spanner/Database.yaml | 1 + mmv1/products/spanner/Instance.yaml | 1 + mmv1/products/spanner/InstanceConfig.yaml | 1 + mmv1/products/storage/HmacKey.yaml | 1 + .../vertexai/IndexEndpointDeployedIndex.yaml | 1 + mmv1/products/vmwareengine/PrivateCloud.yaml | 1 + mmv1/products/vpcaccess/Connector.yaml | 1 + 75 files changed, 201 insertions(+), 85 deletions(-) diff --git a/mmv1/products/activedirectory/DomainTrust.yaml b/mmv1/products/activedirectory/DomainTrust.yaml index 93771ad0c432..ed54fcf8c984 100644 --- a/mmv1/products/activedirectory/DomainTrust.yaml +++ b/mmv1/products/activedirectory/DomainTrust.yaml @@ -51,6 +51,7 @@ nested_query: - trusts is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/active_directory_domain_trust.go.tmpl' update_encoder: 'templates/terraform/update_encoder/active_directory_domain_trust.go.tmpl' diff --git a/mmv1/products/apigee/DeveloperApp.yaml b/mmv1/products/apigee/DeveloperApp.yaml index de66238ac526..55b07513f3bb 100644 --- a/mmv1/products/apigee/DeveloperApp.yaml +++ b/mmv1/products/apigee/DeveloperApp.yaml @@ -29,6 +29,7 @@ update_mask: false update_verb: "PUT" import_format: - "{{org_id}}/developers/{{developer_email}}/apps/{{name}}" +flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/apigee_developer_app.go.tmpl" custom_import: "templates/terraform/custom_import/apigee_developer_app.go.tmpl" diff --git a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml index 972482ae7432..e640c4947492 100644 --- a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml +++ b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml @@ -37,6 +37,7 @@ async: import_format: - '{{env_id}}' id_format: '{{env_id}}' +flatten_all_in_method: true custom_code: custom_import: 'templates/terraform/custom_import/apigee_env_addons.go.tmpl' decoder: 'templates/terraform/decoders/apigee_env_addons.go.tmpl' diff --git a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml index 938d328a6a92..bdc8a878ec5b 100644 --- a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml +++ b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml @@ -34,6 +34,7 @@ timeouts: update_minutes: 20 delete_minutes: 1 autogen_async: true +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/apigee_environment_keyvaluemaps.go.tmpl' custom_create: 'templates/terraform/custom_create/apigee_environment_keyvaluemaps.go.tmpl' diff --git a/mmv1/products/apigee/NatAddress.yaml b/mmv1/products/apigee/NatAddress.yaml index 916e33d2be46..3ab99203e109 100644 --- a/mmv1/products/apigee/NatAddress.yaml +++ b/mmv1/products/apigee/NatAddress.yaml @@ -40,6 +40,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/apigee_nat_address.go.tmpl' encoder: 'templates/terraform/encoders/apigee_nat_address.go.tmpl' diff --git a/mmv1/products/appengine/DomainMapping.yaml b/mmv1/products/appengine/DomainMapping.yaml index 1e9995803021..42234352b931 100644 --- a/mmv1/products/appengine/DomainMapping.yaml +++ b/mmv1/products/appengine/DomainMapping.yaml @@ -39,6 +39,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/app_engine_domain_mapping.go.tmpl' examples: diff --git a/mmv1/products/backupdr/BackupPlan.yaml b/mmv1/products/backupdr/BackupPlan.yaml index 39cccd01c1d7..3aec2d94f787 100644 --- a/mmv1/products/backupdr/BackupPlan.yaml +++ b/mmv1/products/backupdr/BackupPlan.yaml @@ -29,6 +29,7 @@ timeouts: insert_minutes: 60 update_minutes: 60 delete_minutes: 60 +flatten_all_in_method: true custom_code: tgc_decoder: 'templates/tgc_next/decoders/backup_dr_backup_plan.go.tmpl' include_in_tgc_next: true diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 698674c9f1c4..ffb52e512405 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -38,7 +38,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true -tgc_include_handwritten_tests: true flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_dataset.go.tmpl' diff --git a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml index bc965f172b43..69a1c860d173 100644 --- a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml @@ -29,6 +29,7 @@ self_link: 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscrip create_url: 'projects/{{data_exchange_project}}/locations/{{data_exchange_location}}/dataExchanges/{{data_exchange_id}}:subscribe' import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' encoder: 'templates/terraform/encoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' diff --git a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml index e9b68a3ee1c9..48b6ae02f804 100644 --- a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml @@ -29,6 +29,7 @@ create_url: 'projects/{{project}}/locations/{{location}}/dataExchanges/{{data_ex immutable: true import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' +flatten_all_in_method: true custom_code: constants: templates/terraform/constants/bigqueryanalyticshub_listing_subscription.go.tmpl decoder: 'templates/terraform/decoders/bigqueryanalyticshub_listing_subscription.go.tmpl' diff --git a/mmv1/products/bigquerydatatransfer/Config.yaml b/mmv1/products/bigquerydatatransfer/Config.yaml index b7aef36e1dbb..c8b0608a32ec 100644 --- a/mmv1/products/bigquerydatatransfer/Config.yaml +++ b/mmv1/products/bigquerydatatransfer/Config.yaml @@ -34,6 +34,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_data_transfer.go.tmpl' encoder: 'templates/terraform/encoders/bigquery_data_transfer.go.tmpl' diff --git a/mmv1/products/cloudasset/FolderFeed.yaml b/mmv1/products/cloudasset/FolderFeed.yaml index 483ae1c4cb3c..5d6e4530b269 100644 --- a/mmv1/products/cloudasset/FolderFeed.yaml +++ b/mmv1/products/cloudasset/FolderFeed.yaml @@ -33,6 +33,7 @@ timeouts: update_minutes: 20 delete_minutes: 20 collection_url_key: 'feeds' +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/cloud_asset_feed.go.tmpl' pre_create: 'templates/terraform/pre_create/cloud_asset_feed.go.tmpl' diff --git a/mmv1/products/cloudasset/OrganizationFeed.yaml b/mmv1/products/cloudasset/OrganizationFeed.yaml index b6bc05e7677d..e47ec3abbeba 100644 --- a/mmv1/products/cloudasset/OrganizationFeed.yaml +++ b/mmv1/products/cloudasset/OrganizationFeed.yaml @@ -33,6 +33,7 @@ timeouts: update_minutes: 20 delete_minutes: 20 collection_url_key: 'feeds' +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/cloud_asset_feed.go.tmpl' pre_create: 'templates/terraform/pre_create/cloud_asset_feed.go.tmpl' diff --git a/mmv1/products/cloudbilling/ProjectInfo.yaml b/mmv1/products/cloudbilling/ProjectInfo.yaml index b692332973cb..a6bb1b125a24 100644 --- a/mmv1/products/cloudbilling/ProjectInfo.yaml +++ b/mmv1/products/cloudbilling/ProjectInfo.yaml @@ -27,7 +27,11 @@ id_format: projects/{{project}} import_format: - projects/{{%project}} - '{{%project}}' -cai_asset_name_format: projects/{{project}}/billingInfo +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/billing_project_info.go.tmpl decoder: templates/terraform/decoders/billing_project_info.go.tmpl diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 9c3aa87e6ac8..a61e08b4db81 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -24,7 +24,23 @@ cai_base_url: projects/{{project}}/locations/{{location}}/DomainMappings kind: DomainMapping id_format: locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}} import_format: - - locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}} + - 'locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + type: 'PollAsync' + check_response_func_existence: 'PollCheckKnativeStatusFunc(res)' + check_response_func_absence: 'transport_tpg.PollCheckForAbsence' + suppress_error: false + target_occurrences: 1 + actions: ['create', 'update'] +flatten_all_in_method: true +custom_code: + constants: 'templates/terraform/constants/cloud_run_domain_mapping.go.tmpl' + encoder: 'templates/terraform/encoders/cloud_run_domain_mapping.go.tmpl' + decoder: 'templates/terraform/decoders/cloud_run.go.tmpl' custom_diff: - hasMetadata async: diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 6f8fe3a5cadc..fe5e906f21f8 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -51,6 +51,7 @@ iam_policy: import_format: - 'projects/{{project}}/locations/{{location}}/services/{{service}}' - '{{service}}' +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/cloud_run_service.go.tmpl' encoder: 'templates/terraform/encoders/cloud_run_service.go.tmpl' diff --git a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml index eba8c82256b6..f5dba0b2553d 100644 --- a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml @@ -45,6 +45,7 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_disk_resource_policies_attachment.go.tmpl' decoder: 'templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl' diff --git a/mmv1/products/compute/FirewallPolicyWithRules.yaml b/mmv1/products/compute/FirewallPolicyWithRules.yaml index 736a927304dc..96a50146221c 100644 --- a/mmv1/products/compute/FirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/FirewallPolicyWithRules.yaml @@ -29,6 +29,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/GlobalNetworkEndpoint.yaml b/mmv1/products/compute/GlobalNetworkEndpoint.yaml index 740696cb9e60..06a6a3a02faf 100644 --- a/mmv1/products/compute/GlobalNetworkEndpoint.yaml +++ b/mmv1/products/compute/GlobalNetworkEndpoint.yaml @@ -53,6 +53,7 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_global_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/Instance.yaml b/mmv1/products/compute/Instance.yaml index 193b3cc410dd..f1a6acadb180 100644 --- a/mmv1/products/compute/Instance.yaml +++ b/mmv1/products/compute/Instance.yaml @@ -37,6 +37,7 @@ iam_policy: allowed_iam_role: 'roles/compute.osLogin' parent_resource_attribute: 'instance_name' iam_conditions_request_type: 'QUERY_PARAM' +flatten_all_in_method: true custom_code: examples: - name: 'instance_basic' diff --git a/mmv1/products/compute/NetworkEndpoint.yaml b/mmv1/products/compute/NetworkEndpoint.yaml index 67b16dc943d7..11b29e0126fc 100644 --- a/mmv1/products/compute/NetworkEndpoint.yaml +++ b/mmv1/products/compute/NetworkEndpoint.yaml @@ -59,6 +59,7 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/unwrap_resource.go.tmpl' diff --git a/mmv1/products/compute/NetworkEndpoints.yaml b/mmv1/products/compute/NetworkEndpoints.yaml index 4bc74355c5b1..37edf62b0647 100644 --- a/mmv1/products/compute/NetworkEndpoints.yaml +++ b/mmv1/products/compute/NetworkEndpoints.yaml @@ -58,6 +58,7 @@ async: resource_inside_response: false identity: - networkEndpointGroup +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/network_endpoints.go.tmpl' encoder: 'templates/terraform/encoders/compute_network_endpoints.go.tmpl' diff --git a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml index f82f8c7981af..a7b86a90683d 100644 --- a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml @@ -31,6 +31,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml index aa47a8ff28ab..c0cef289cb5f 100644 --- a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml @@ -12,19 +12,32 @@ # limitations under the License. --- -name: RegionDiskResourcePolicyAttachment +name: 'RegionDiskResourcePolicyAttachment' api_resource_type_kind: Disk description: | Adds existing resource policies to a disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation. ~> **Note:** This resource does not support zonal disks (`google_compute_disk`). For zonal disks, please refer to [`google_compute_disk_resource_policy_attachment`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_disk_resource_policy_attachment) -base_url: projects/{{project}}/regions/{{region}}/disks/{{disk}} +docs: +id_format: '{{project}}/{{region}}/{{disk}}/{{name}}' +base_url: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}' +self_link: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}' +create_url: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}/addResourcePolicies' +delete_url: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}/removeResourcePolicies' +delete_verb: 'POST' immutable: true -self_link: projects/{{project}}/regions/{{region}}/disks/{{disk}} -create_url: projects/{{project}}/regions/{{region}}/disks/{{disk}}/addResourcePolicies -delete_url: projects/{{project}}/regions/{{region}}/disks/{{disk}}/removeResourcePolicies -delete_verb: POST +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + result: + resource_inside_response: false identity: - name nested_query: @@ -32,42 +45,40 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false -id_format: '{{project}}/{{region}}/{{disk}}/{{name}}' -async: - operation: - base_url: '{{op_id}}' +flatten_all_in_method: true custom_code: - encoder: templates/terraform/encoders/compute_region_disk_resource_policies_attachment.go.tmpl - decoder: templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl - pre_delete: templates/terraform/pre_delete/compute_region_disk_resource_policies_attachment.go.tmpl + encoder: 'templates/terraform/encoders/compute_region_disk_resource_policies_attachment.go.tmpl' + decoder: 'templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl' + pre_delete: 'templates/terraform/pre_delete/compute_region_disk_resource_policies_attachment.go.tmpl' examples: - - name: region_disk_resource_policy_attachment_basic - primary_resource_id: attachment + - name: 'region_disk_resource_policy_attachment_basic' + primary_resource_id: 'attachment' vars: - base_disk_name: my-base-disk - disk_name: my-disk - policy_name: my-resource-policy - snapshot_name: my-snapshot + base_disk_name: 'my-base-disk' + snapshot_name: 'my-snapshot' + disk_name: 'my-disk' + policy_name: 'my-resource-policy' parameters: - - name: disk + - name: 'disk' type: ResourceRef - required: true description: | The name of the regional disk in which the resource policies are attached to. url_param_only: true - resource: Disk - imports: name - - name: region + required: true + resource: 'Disk' + imports: 'name' + - name: 'region' type: ResourceRef - description: A reference to the region where the disk resides. + description: 'A reference to the region where the disk resides.' url_param_only: true - resource: Region - imports: name + required: false default_from_api: true + resource: 'Region' + imports: 'name' properties: - - name: name + - name: 'name' type: String - required: true description: | The resource policy to be attached to the disk for scheduling snapshot creation. Do not specify the self link. + required: true diff --git a/mmv1/products/compute/RegionNetworkEndpoint.yaml b/mmv1/products/compute/RegionNetworkEndpoint.yaml index 979a9d3126e7..37da1a094851 100644 --- a/mmv1/products/compute/RegionNetworkEndpoint.yaml +++ b/mmv1/products/compute/RegionNetworkEndpoint.yaml @@ -55,6 +55,7 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_region_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml index 3690677e0024..36777743df96 100644 --- a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml @@ -31,6 +31,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/ResourcePolicyAttachment.yaml b/mmv1/products/compute/ResourcePolicyAttachment.yaml index 9d41f9a760c4..c739b3171857 100644 --- a/mmv1/products/compute/ResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/ResourcePolicyAttachment.yaml @@ -12,7 +12,7 @@ # limitations under the License. --- -name: ResourcePolicyAttachment +name: 'ResourcePolicyAttachment' api_resource_type_kind: Instance description: | Adds existing resource policies to a compute instance. You can only add one policy @@ -21,12 +21,25 @@ description: | This resource can be used instead of setting the resource_policy directly in the compute instance resource to avoid dependency issues when using instance-level IAM permissions. -base_url: projects/{{project}}/zones/{{zone}}/instances/{{instance}} +docs: +id_format: '{{project}}/{{zone}}/{{instance}}/{{name}}' +base_url: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}' +self_link: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}' +create_url: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}/addResourcePolicies' +delete_url: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}/removeResourcePolicies' +delete_verb: 'POST' immutable: true -self_link: projects/{{project}}/zones/{{zone}}/instances/{{instance}} -create_url: projects/{{project}}/zones/{{zone}}/instances/{{instance}}/addResourcePolicies -delete_url: projects/{{project}}/zones/{{zone}}/instances/{{instance}}/removeResourcePolicies -delete_verb: POST +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + result: + resource_inside_response: false identity: - name nested_query: @@ -34,41 +47,39 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false -id_format: '{{project}}/{{zone}}/{{instance}}/{{name}}' -async: - operation: - base_url: '{{op_id}}' +flatten_all_in_method: true custom_code: - encoder: templates/terraform/encoders/compute_resource_policy_attachment.go.tmpl - decoder: templates/terraform/decoders/compute_resource_policy_attachment.go.tmpl - pre_delete: templates/terraform/pre_delete/compute_resource_policy_attachment.go.tmpl + encoder: 'templates/terraform/encoders/compute_resource_policy_attachment.go.tmpl' + decoder: 'templates/terraform/decoders/compute_resource_policy_attachment.go.tmpl' + pre_delete: 'templates/terraform/pre_delete/compute_resource_policy_attachment.go.tmpl' examples: - - name: compute_resource_policy_attachment_basic - primary_resource_id: attachment + - name: 'compute_resource_policy_attachment_basic' + primary_resource_id: 'attachment' vars: - instance_name: my-instance - policy_name: my-resource-policy + instance_name: 'my-instance' + policy_name: 'my-resource-policy' parameters: - - name: instance + - name: 'instance' type: ResourceRef - required: true description: | The name of the instance in which the resource policies are attached to. url_param_only: true - resource: Instance - imports: name - - name: zone + required: true + resource: 'Instance' + imports: 'name' + - name: 'zone' type: ResourceRef - description: A reference to the zone where the instance resides. + description: 'A reference to the zone where the instance resides.' url_param_only: true - resource: Zone - imports: name + required: false ignore_read: true default_from_api: true + resource: 'Zone' + imports: 'name' properties: - - name: name + - name: 'name' type: String - required: true description: | The resource policy to be attached to the instance for scheduling start/stop operations. Do not specify the self link. + required: true diff --git a/mmv1/products/compute/RouterRoutePolicy.yaml b/mmv1/products/compute/RouterRoutePolicy.yaml index 0d4dd3bc8069..adf91fc1726f 100644 --- a/mmv1/products/compute/RouterRoutePolicy.yaml +++ b/mmv1/products/compute/RouterRoutePolicy.yaml @@ -42,6 +42,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/unwrap_route_policy_resource.go.tmpl' examples: diff --git a/mmv1/products/containeranalysis/Note.yaml b/mmv1/products/containeranalysis/Note.yaml index 5effb9e85704..a92a2cf9e8a9 100644 --- a/mmv1/products/containeranalysis/Note.yaml +++ b/mmv1/products/containeranalysis/Note.yaml @@ -42,6 +42,7 @@ iam_policy: import_format: - 'projects/{{project}}/notes/{{name}}' - '{{name}}' +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/containeranalysis_attestation_field_name.go.tmpl' decoder: 'templates/terraform/decoders/containeranalysis_attestation_field_name.go.tmpl' diff --git a/mmv1/products/containeranalysis/Occurrence.yaml b/mmv1/products/containeranalysis/Occurrence.yaml index 78f4e19ecfce..4a94beead5fd 100644 --- a/mmv1/products/containeranalysis/Occurrence.yaml +++ b/mmv1/products/containeranalysis/Occurrence.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/containeranalysis_occurrence.go.tmpl' update_encoder: 'templates/terraform/update_encoder/containeranalysis_occurrence.go.tmpl' diff --git a/mmv1/products/dataplex/Entry.yaml b/mmv1/products/dataplex/Entry.yaml index a9ba0c7ac46a..1e720b34d5a2 100644 --- a/mmv1/products/dataplex/Entry.yaml +++ b/mmv1/products/dataplex/Entry.yaml @@ -39,6 +39,7 @@ update_mask: true import_format: - 'projects/{{project}}/locations/{{location}}/entryGroups/{{entry_group_id}}/entries/{{entry_id}}' +flatten_all_in_method: true custom_code: constants: templates/terraform/constants/dataplex_entry.go.tmpl decoder: templates/terraform/decoders/dataplex_entry.go.tmpl diff --git a/mmv1/products/dataproc/Batch.yaml b/mmv1/products/dataproc/Batch.yaml index d0f07545700b..2d641151ea63 100644 --- a/mmv1/products/dataproc/Batch.yaml +++ b/mmv1/products/dataproc/Batch.yaml @@ -39,6 +39,7 @@ async: base_url: '{{op_id}}' autogen_async: true include_in_tgc_next: true +flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/cloud_dataproc_batch.go.tmpl constants: templates/terraform/constants/cloud_dataproc_batch.go.tmpl diff --git a/mmv1/products/dlp/DeidentifyTemplate.yaml b/mmv1/products/dlp/DeidentifyTemplate.yaml index 8ff5250fb9d6..b4396a566980 100644 --- a/mmv1/products/dlp/DeidentifyTemplate.yaml +++ b/mmv1/products/dlp/DeidentifyTemplate.yaml @@ -30,6 +30,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/wrap_object_with_template_id.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/DiscoveryConfig.yaml b/mmv1/products/dlp/DiscoveryConfig.yaml index 4c27e6d0ce49..6db8dec372d5 100644 --- a/mmv1/products/dlp/DiscoveryConfig.yaml +++ b/mmv1/products/dlp/DiscoveryConfig.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/InspectTemplate.yaml b/mmv1/products/dlp/InspectTemplate.yaml index 5ea7f2adb359..1768debd78c7 100644 --- a/mmv1/products/dlp/InspectTemplate.yaml +++ b/mmv1/products/dlp/InspectTemplate.yaml @@ -30,6 +30,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/wrap_object_with_template_id.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/JobTrigger.yaml b/mmv1/products/dlp/JobTrigger.yaml index 873b07e2fd8d..3a0b809b1cea 100644 --- a/mmv1/products/dlp/JobTrigger.yaml +++ b/mmv1/products/dlp/JobTrigger.yaml @@ -30,6 +30,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/dlp_job_trigger.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/StoredInfoType.yaml b/mmv1/products/dlp/StoredInfoType.yaml index acb2700e2bce..af6492d0b642 100644 --- a/mmv1/products/dlp/StoredInfoType.yaml +++ b/mmv1/products/dlp/StoredInfoType.yaml @@ -37,6 +37,7 @@ async: suppress_error: false target_occurrences: 1 actions: ['create'] +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/dlp_stored_info_type.go.tmpl' encoder: 'templates/terraform/encoders/dlp_stored_info_type.go.tmpl' diff --git a/mmv1/products/firebasedatabase/Instance.yaml b/mmv1/products/firebasedatabase/Instance.yaml index 469473b18e8a..4bf27c916d25 100644 --- a/mmv1/products/firebasedatabase/Instance.yaml +++ b/mmv1/products/firebasedatabase/Instance.yaml @@ -31,6 +31,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/firebase_database_instance.go.tmpl' decoder: 'templates/terraform/decoders/firebase_database_instance.go.tmpl' diff --git a/mmv1/products/firestore/Document.yaml b/mmv1/products/firestore/Document.yaml index 604724f3d6ed..f15b6c8fd91d 100644 --- a/mmv1/products/firestore/Document.yaml +++ b/mmv1/products/firestore/Document.yaml @@ -40,6 +40,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/firestore_document.go.tmpl' custom_import: 'templates/terraform/custom_import/firestore_document.go.tmpl' diff --git a/mmv1/products/healthcare/Dataset.yaml b/mmv1/products/healthcare/Dataset.yaml index d8313d98ba65..6e53ef81e584 100644 --- a/mmv1/products/healthcare/Dataset.yaml +++ b/mmv1/products/healthcare/Dataset.yaml @@ -32,6 +32,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' error_retry_predicates: diff --git a/mmv1/products/healthcare/DicomStore.yaml b/mmv1/products/healthcare/DicomStore.yaml index 2e2c9b448e33..8409bf02ae5e 100644 --- a/mmv1/products/healthcare/DicomStore.yaml +++ b/mmv1/products/healthcare/DicomStore.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_dicom_store.go.tmpl' diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index e8d5fcdcd9b2..660786dd4786 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_fhir_store.go.tmpl' diff --git a/mmv1/products/healthcare/Hl7V2Store.yaml b/mmv1/products/healthcare/Hl7V2Store.yaml index c2bea16e4880..b5a076b7a476 100644 --- a/mmv1/products/healthcare/Hl7V2Store.yaml +++ b/mmv1/products/healthcare/Hl7V2Store.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_hl7_v2_store.go.tmpl' diff --git a/mmv1/products/healthcare/PipelineJob.yaml b/mmv1/products/healthcare/PipelineJob.yaml index 260f4380a098..b2fae67c1dda 100644 --- a/mmv1/products/healthcare/PipelineJob.yaml +++ b/mmv1/products/healthcare/PipelineJob.yaml @@ -71,6 +71,7 @@ examples: source_fhirstore_name: 'source_fhir_store' dest_fhirstore_name: 'dest_fhir_store' bucket_name: 'example_bucket_name' +flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/long_name_to_self_link.go.tmpl parameters: diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml index a737e20e0673..e4a0c240b7d9 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml @@ -28,6 +28,7 @@ update_mask: true import_format: - 'projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/namespaces/{{workload_identity_pool_namespace_id}}/managedIdentities/{{workload_identity_pool_managed_identity_id}}' autogen_async: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool_managed_identity.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml index 71ec2fc53efb..c5349e15230b 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml @@ -29,6 +29,7 @@ update_mask: true import_format: - 'projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/namespaces/{{workload_identity_pool_namespace_id}}' autogen_async: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool_namespace.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml index caf7a27ba67b..27fef881088e 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml @@ -39,6 +39,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool_provider.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iamworkforcepool/OauthClient.yaml b/mmv1/products/iamworkforcepool/OauthClient.yaml index 8fd0b6edc4d9..a57d0629cfd9 100644 --- a/mmv1/products/iamworkforcepool/OauthClient.yaml +++ b/mmv1/products/iamworkforcepool/OauthClient.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl" test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client.go.tmpl" diff --git a/mmv1/products/iamworkforcepool/OauthClientCredential.yaml b/mmv1/products/iamworkforcepool/OauthClientCredential.yaml index bacf221fadcd..0eab9a7c47e8 100644 --- a/mmv1/products/iamworkforcepool/OauthClientCredential.yaml +++ b/mmv1/products/iamworkforcepool/OauthClientCredential.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl" test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client_credential.go.tmpl" diff --git a/mmv1/products/iamworkforcepool/WorkforcePool.yaml b/mmv1/products/iamworkforcepool/WorkforcePool.yaml index eb874320e32d..150078065a91 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePool.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePool.yaml @@ -43,6 +43,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workforce_pool.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml index 2370e40ebee1..a8f53653b190 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml @@ -31,6 +31,7 @@ update_mask: true timeouts: insert_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' post_create: 'templates/terraform/post_create/sleep.go.tmpl' diff --git a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml index 1023d021c4c6..b9c27ecc48e7 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml @@ -31,6 +31,7 @@ update_mask: true timeouts: insert_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' post_create: 'templates/terraform/post_create/sleep.go.tmpl' diff --git a/mmv1/products/integrations/Client.yaml b/mmv1/products/integrations/Client.yaml index a3ddc281162e..01b336556db9 100644 --- a/mmv1/products/integrations/Client.yaml +++ b/mmv1/products/integrations/Client.yaml @@ -34,6 +34,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/integrations_client.go.tmpl' pre_create: 'templates/terraform/pre_create/integrations_client.go.tmpl' diff --git a/mmv1/products/kms/KeyHandle.yaml b/mmv1/products/kms/KeyHandle.yaml index 6c4fe2505432..75ba2a99faf6 100644 --- a/mmv1/products/kms/KeyHandle.yaml +++ b/mmv1/products/kms/KeyHandle.yaml @@ -46,6 +46,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/kms.go.tmpl' tgc_decoder: 'templates/tgc_next/decoders/kms.go.tmpl' diff --git a/mmv1/products/kms/KeyRing.yaml b/mmv1/products/kms/KeyRing.yaml index 6cca3351f8a0..2165f2448cb0 100644 --- a/mmv1/products/kms/KeyRing.yaml +++ b/mmv1/products/kms/KeyRing.yaml @@ -38,6 +38,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: tgc_ignore_terraform_decoder: true encoder: 'templates/terraform/encoders/send_nil_body.go.tmpl' diff --git a/mmv1/products/kms/SecretCiphertext.yaml b/mmv1/products/kms/SecretCiphertext.yaml index f85549ea38b2..ffe846689b78 100644 --- a/mmv1/products/kms/SecretCiphertext.yaml +++ b/mmv1/products/kms/SecretCiphertext.yaml @@ -12,7 +12,7 @@ # limitations under the License. --- -name: SecretCiphertext +name: 'SecretCiphertext' api_resource_type_kind: CryptoKey description: | Encrypts secret data with Google Cloud KMS and provides access to the ciphertext. @@ -24,56 +24,62 @@ description: | data outside of resource definitions. references: guides: - Encrypting and decrypting data with a symmetric key: https://cloud.google.com/kms/docs/encrypt-decrypt - api: https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt + 'Encrypting and decrypting data with a symmetric key': 'https://cloud.google.com/kms/docs/encrypt-decrypt' + api: 'https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt' +docs: +id_format: '{{crypto_key}}/{{ciphertext}}' base_url: '{{crypto_key}}' -immutable: true self_link: '{{crypto_key}}' create_url: '{{crypto_key}}:encrypt' -id_format: '{{crypto_key}}/{{ciphertext}}' -exclude_import: true exclude_delete: true -supports_indirect_user_project_override: true -exclude_tgc: true +immutable: true +exclude_import: true +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +flatten_all_in_method: true custom_code: - decoder: templates/terraform/decoders/noop.go.tmpl - post_create: templates/terraform/post_create/kms_secret_ciphertext.go.tmpl + decoder: 'templates/terraform/decoders/noop.go.tmpl' + post_create: 'templates/terraform/post_create/kms_secret_ciphertext.go.tmpl' +exclude_tgc: true +supports_indirect_user_project_override: true examples: - - name: kms_secret_ciphertext_basic - primary_resource_id: my_password - exclude_test: true + - name: 'kms_secret_ciphertext_basic' + primary_resource_id: 'my_password' vars: - instance_name: my-instance + instance_name: 'my-instance' + exclude_test: true parameters: - - name: cryptoKey + - name: 'cryptoKey' type: String - required: true description: | The full name of the CryptoKey that will be used to encrypt the provided plaintext. Format: `'projects/{{project}}/locations/{{location}}/keyRings/{{keyRing}}/cryptoKeys/{{cryptoKey}}'` url_param_only: true + required: true ignore_read: true properties: - - name: plaintext + - name: 'plaintext' type: String - required: true description: | The plaintext to be encrypted. - sensitive: true + required: true ignore_read: true - custom_expand: templates/terraform/custom_expand/base64.go.tmpl - - name: additionalAuthenticatedData + sensitive: true + custom_expand: 'templates/terraform/custom_expand/base64.go.tmpl' + - name: 'additionalAuthenticatedData' type: String description: | The additional authenticated data used for integrity checks during encryption and decryption. - sensitive: true ignore_read: true - custom_expand: templates/terraform/custom_expand/base64.go.tmpl - - name: ciphertext + sensitive: true + custom_expand: 'templates/terraform/custom_expand/base64.go.tmpl' + - name: 'ciphertext' type: String description: | Contains the result of encrypting the provided plaintext, encoded in base64. - output: true ignore_read: true + output: true validation: - function: verify.ValidateBase64String + function: 'verify.ValidateBase64String' diff --git a/mmv1/products/memorystore/Instance.yaml b/mmv1/products/memorystore/Instance.yaml index b29f279c7f3e..f31da1ce1fde 100644 --- a/mmv1/products/memorystore/Instance.yaml +++ b/mmv1/products/memorystore/Instance.yaml @@ -40,6 +40,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/memorystore_instance.go.tmpl' decoder: 'templates/terraform/decoders/memorystore_instance.go.tmpl' diff --git a/mmv1/products/monitoring/MonitoredProject.yaml b/mmv1/products/monitoring/MonitoredProject.yaml index 8380e7b3dc1d..891bb5c83036 100644 --- a/mmv1/products/monitoring/MonitoredProject.yaml +++ b/mmv1/products/monitoring/MonitoredProject.yaml @@ -34,6 +34,7 @@ async: actions: ['create', 'delete'] operation: base_url: '{{op_id}}' +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/monitoring_monitored_project.go.tmpl' test_constants: 'templates/terraform/test_constants/monitoring_monitored_project.go.tmpl' diff --git a/mmv1/products/monitoring/NotificationChannel.yaml b/mmv1/products/monitoring/NotificationChannel.yaml index c973f860f5d0..196015871c0f 100644 --- a/mmv1/products/monitoring/NotificationChannel.yaml +++ b/mmv1/products/monitoring/NotificationChannel.yaml @@ -49,6 +49,7 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/monitoring_notification_channel.go.tmpl' encoder: 'templates/terraform/encoders/monitoring_notification_channel.go.tmpl' diff --git a/mmv1/products/privateca/CaPool.yaml b/mmv1/products/privateca/CaPool.yaml index c94d9fe272bf..5c28f42e04b0 100644 --- a/mmv1/products/privateca/CaPool.yaml +++ b/mmv1/products/privateca/CaPool.yaml @@ -47,6 +47,7 @@ iam_policy: parent_resource_attribute: 'ca_pool' iam_conditions_request_type: 'QUERY_PARAM_NESTED' example_config_body: 'templates/terraform/iam/example_config_body/privateca_ca_pool.tf.tmpl' +flatten_all_in_method: true custom_code: tgc_decoder: 'templates/tgc_next/decoders/privateca_capool.go.tmpl' examples: diff --git a/mmv1/products/privateca/CertificateAuthority.yaml b/mmv1/products/privateca/CertificateAuthority.yaml index 513ec47fe234..f3aa99c0ba6c 100644 --- a/mmv1/products/privateca/CertificateAuthority.yaml +++ b/mmv1/products/privateca/CertificateAuthority.yaml @@ -45,6 +45,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/privateca_certificate_authority.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/redis/Cluster.yaml b/mmv1/products/redis/Cluster.yaml index dcbca567bbf1..ee8ec507fd91 100644 --- a/mmv1/products/redis/Cluster.yaml +++ b/mmv1/products/redis/Cluster.yaml @@ -116,6 +116,7 @@ async: result: resource_inside_response: false include_in_tgc_next: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/redis_cluster.go.tmpl' decoder: 'templates/terraform/decoders/redis_cluster.go.tmpl' diff --git a/mmv1/products/redis/Instance.yaml b/mmv1/products/redis/Instance.yaml index d317a3ab5e2d..62bfd9f0b4c3 100644 --- a/mmv1/products/redis/Instance.yaml +++ b/mmv1/products/redis/Instance.yaml @@ -38,6 +38,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: extra_schema_entry: 'templates/terraform/extra_schema_entry/redis_instance.tmpl' constants: 'templates/terraform/constants/redis_instance.go.tmpl' diff --git a/mmv1/products/resourcemanager/Lien.yaml b/mmv1/products/resourcemanager/Lien.yaml index 5336c0c33393..18eef62504bd 100644 --- a/mmv1/products/resourcemanager/Lien.yaml +++ b/mmv1/products/resourcemanager/Lien.yaml @@ -44,6 +44,7 @@ nested_query: - liens is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resourcemanager_lien.go.tmpl' test_constants: 'templates/terraform/constants/resourcemanager_lien.go.tpml' diff --git a/mmv1/products/secretmanager/SecretVersion.yaml b/mmv1/products/secretmanager/SecretVersion.yaml index 164643375de9..21077c8d322b 100644 --- a/mmv1/products/secretmanager/SecretVersion.yaml +++ b/mmv1/products/secretmanager/SecretVersion.yaml @@ -41,6 +41,7 @@ timeouts: delete_minutes: 20 include_in_tgc_next: true cai_asset_name_format: '{{secret}}/versions/{{version}}' +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_destroyed_state_as_gone.tmpl' pre_create: 'templates/terraform/pre_create/secret_manager_secret_version.go.tmpl' diff --git a/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml b/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml index 30d5b1289d65..48b6590e8e75 100644 --- a/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml +++ b/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml @@ -38,6 +38,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_destroyed_state_as_gone.tmpl' pre_create: 'templates/terraform/pre_create/secret_manager_regional_secret_version.go.tmpl' diff --git a/mmv1/products/servicedirectory/Endpoint.yaml b/mmv1/products/servicedirectory/Endpoint.yaml index af189501b797..e1443f8dbf5d 100644 --- a/mmv1/products/servicedirectory/Endpoint.yaml +++ b/mmv1/products/servicedirectory/Endpoint.yaml @@ -30,6 +30,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: custom_import: 'templates/terraform/custom_import/service_directory_endpoint.go.tmpl' encoder: 'templates/terraform/encoders/service_directory_metadata_to_annotations.go.tmpl' diff --git a/mmv1/products/spanner/BackupSchedule.yaml b/mmv1/products/spanner/BackupSchedule.yaml index 485c6f739bac..3a0e4598a6f7 100644 --- a/mmv1/products/spanner/BackupSchedule.yaml +++ b/mmv1/products/spanner/BackupSchedule.yaml @@ -41,6 +41,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/spanner_schedule_backup.go.tmpl' decoder: 'templates/terraform/decoders/spanner_schedule_backup.go.tmpl' diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index a8e189ed4bde..dd99b1016c43 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -51,6 +51,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_database.go.tmpl' encoder: 'templates/terraform/encoders/spanner_database.go.tmpl' diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 95053fa49e9f..a5257450bb2d 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -42,6 +42,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_instance.go.tmpl' encoder: 'templates/terraform/encoders/spanner_instance.go.tmpl' diff --git a/mmv1/products/spanner/InstanceConfig.yaml b/mmv1/products/spanner/InstanceConfig.yaml index d1c00291d72f..aef9c8a041a0 100644 --- a/mmv1/products/spanner/InstanceConfig.yaml +++ b/mmv1/products/spanner/InstanceConfig.yaml @@ -41,6 +41,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_instance_config.go.tmpl' encoder: 'templates/terraform/encoders/spanner_instance_config.go.tmpl' diff --git a/mmv1/products/storage/HmacKey.yaml b/mmv1/products/storage/HmacKey.yaml index 1df033b441f1..bd5e933802f0 100644 --- a/mmv1/products/storage/HmacKey.yaml +++ b/mmv1/products/storage/HmacKey.yaml @@ -47,6 +47,7 @@ async: suppress_error: false target_occurrences: 1 actions: ['create'] +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' post_create: 'templates/terraform/post_create/storage_hmac_key.go.tmpl' diff --git a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml index 9692370bf120..fdcd37c7dfc2 100644 --- a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml +++ b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml @@ -46,6 +46,7 @@ async: result: resource_inside_response: true include_project: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/vertex_ai_index_endpoint_deployed_index.go.tmpl' update_encoder: 'templates/terraform/update_encoder/vertex_ai_index_endpoint_deployed_index.go.tmpl' diff --git a/mmv1/products/vmwareengine/PrivateCloud.yaml b/mmv1/products/vmwareengine/PrivateCloud.yaml index 4eedf7fe0504..14239dfd65f1 100644 --- a/mmv1/products/vmwareengine/PrivateCloud.yaml +++ b/mmv1/products/vmwareengine/PrivateCloud.yaml @@ -41,6 +41,7 @@ async: delete_minutes: 150 result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/vmwareengine_private_cloud.go.tmpl' update_encoder: 'templates/terraform/update_encoder/private_cloud.go.tmpl' diff --git a/mmv1/products/vpcaccess/Connector.yaml b/mmv1/products/vpcaccess/Connector.yaml index 45a737196666..7bfa931a20a6 100644 --- a/mmv1/products/vpcaccess/Connector.yaml +++ b/mmv1/products/vpcaccess/Connector.yaml @@ -38,6 +38,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/no_send_name.go.tmpl' decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' From 1a77222999a78c87cae91aef9dc8192a110382dd Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 19 Feb 2026 10:08:07 -0800 Subject: [PATCH 006/100] remove spanner.Instance and spanner.InstanceConfig - flatteners clash --- mmv1/products/spanner/Instance.yaml | 1 - mmv1/products/spanner/InstanceConfig.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index a5257450bb2d..95053fa49e9f 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -42,7 +42,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_instance.go.tmpl' encoder: 'templates/terraform/encoders/spanner_instance.go.tmpl' diff --git a/mmv1/products/spanner/InstanceConfig.yaml b/mmv1/products/spanner/InstanceConfig.yaml index aef9c8a041a0..d1c00291d72f 100644 --- a/mmv1/products/spanner/InstanceConfig.yaml +++ b/mmv1/products/spanner/InstanceConfig.yaml @@ -41,7 +41,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_instance_config.go.tmpl' encoder: 'templates/terraform/encoders/spanner_instance_config.go.tmpl' From acb64eb5ce61f24e5eb09623a62f0a6cf11a81b8 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 20 Feb 2026 16:41:55 -0800 Subject: [PATCH 007/100] conflict fixe --- mmv1/api/resource.go | 3 +++ mmv1/products/cloudrun/DomainMapping.yaml | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index bffb7033da2b..3f29b38b38e8 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -368,6 +368,9 @@ type Resource struct { CustomCode resource.CustomCode `yaml:"custom_code,omitempty"` + // If true it will generate all flatteners in a flatten{{resourceName}} method instead of generating all flatteners in Read() + FlattenAllInMethod bool `yaml:"flatten_all_in_method,omitempty"` + // Examples in documentation. Backed by generated tests, and have // corresponding OiCS walkthroughs. Examples []*resource.Examples `yaml:"examples,omitempty"` diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index a61e08b4db81..2dd184019505 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -43,14 +43,6 @@ custom_code: decoder: 'templates/terraform/decoders/cloud_run.go.tmpl' custom_diff: - hasMetadata -async: - type: PollAsync - actions: - - create - - update - check_response_func_existence: PollCheckKnativeStatusFunc(res) - check_response_func_absence: transport_tpg.PollCheckForAbsence - target_occurrences: 1 error_retry_predicates: - transport_tpg.IsCloudRunCreationConflict schema_version: 1 From d38f80261e260ac68a23c917105ce8c013f4db28 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Sat, 21 Feb 2026 12:10:52 -0800 Subject: [PATCH 008/100] revert yamls that got extra updates --- mmv1/products/bigquery/Dataset.yaml | 1 + mmv1/products/cloudbilling/ProjectInfo.yaml | 6 +- mmv1/products/cloudrun/DomainMapping.yaml | 18 +---- .../RegionDiskResourcePolicyAttachment.yaml | 69 ++++++++----------- .../compute/ResourcePolicyAttachment.yaml | 65 ++++++++--------- mmv1/products/kms/SecretCiphertext.yaml | 58 +++++++--------- 6 files changed, 85 insertions(+), 132 deletions(-) diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index ffb52e512405..698674c9f1c4 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -38,6 +38,7 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true +tgc_include_handwritten_tests: true flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_dataset.go.tmpl' diff --git a/mmv1/products/cloudbilling/ProjectInfo.yaml b/mmv1/products/cloudbilling/ProjectInfo.yaml index a6bb1b125a24..b692332973cb 100644 --- a/mmv1/products/cloudbilling/ProjectInfo.yaml +++ b/mmv1/products/cloudbilling/ProjectInfo.yaml @@ -27,11 +27,7 @@ id_format: projects/{{project}} import_format: - projects/{{%project}} - '{{%project}}' -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -flatten_all_in_method: true +cai_asset_name_format: projects/{{project}}/billingInfo custom_code: encoder: templates/terraform/encoders/billing_project_info.go.tmpl decoder: templates/terraform/decoders/billing_project_info.go.tmpl diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 2dd184019505..981e80b12372 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -24,23 +24,7 @@ cai_base_url: projects/{{project}}/locations/{{location}}/DomainMappings kind: DomainMapping id_format: locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}} import_format: - - 'locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}}' -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -async: - type: 'PollAsync' - check_response_func_existence: 'PollCheckKnativeStatusFunc(res)' - check_response_func_absence: 'transport_tpg.PollCheckForAbsence' - suppress_error: false - target_occurrences: 1 - actions: ['create', 'update'] -flatten_all_in_method: true -custom_code: - constants: 'templates/terraform/constants/cloud_run_domain_mapping.go.tmpl' - encoder: 'templates/terraform/encoders/cloud_run_domain_mapping.go.tmpl' - decoder: 'templates/terraform/decoders/cloud_run.go.tmpl' + - locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}} custom_diff: - hasMetadata error_retry_predicates: diff --git a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml index c0cef289cb5f..aa47a8ff28ab 100644 --- a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml @@ -12,32 +12,19 @@ # limitations under the License. --- -name: 'RegionDiskResourcePolicyAttachment' +name: RegionDiskResourcePolicyAttachment api_resource_type_kind: Disk description: | Adds existing resource policies to a disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation. ~> **Note:** This resource does not support zonal disks (`google_compute_disk`). For zonal disks, please refer to [`google_compute_disk_resource_policy_attachment`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_disk_resource_policy_attachment) -docs: -id_format: '{{project}}/{{region}}/{{disk}}/{{name}}' -base_url: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}' -self_link: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}' -create_url: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}/addResourcePolicies' -delete_url: 'projects/{{project}}/regions/{{region}}/disks/{{disk}}/removeResourcePolicies' -delete_verb: 'POST' +base_url: projects/{{project}}/regions/{{region}}/disks/{{disk}} immutable: true -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -async: - actions: ['create', 'delete', 'update'] - type: 'OpAsync' - operation: - base_url: '{{op_id}}' - result: - resource_inside_response: false +self_link: projects/{{project}}/regions/{{region}}/disks/{{disk}} +create_url: projects/{{project}}/regions/{{region}}/disks/{{disk}}/addResourcePolicies +delete_url: projects/{{project}}/regions/{{region}}/disks/{{disk}}/removeResourcePolicies +delete_verb: POST identity: - name nested_query: @@ -45,40 +32,42 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false -flatten_all_in_method: true +id_format: '{{project}}/{{region}}/{{disk}}/{{name}}' +async: + operation: + base_url: '{{op_id}}' custom_code: - encoder: 'templates/terraform/encoders/compute_region_disk_resource_policies_attachment.go.tmpl' - decoder: 'templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl' - pre_delete: 'templates/terraform/pre_delete/compute_region_disk_resource_policies_attachment.go.tmpl' + encoder: templates/terraform/encoders/compute_region_disk_resource_policies_attachment.go.tmpl + decoder: templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl + pre_delete: templates/terraform/pre_delete/compute_region_disk_resource_policies_attachment.go.tmpl examples: - - name: 'region_disk_resource_policy_attachment_basic' - primary_resource_id: 'attachment' + - name: region_disk_resource_policy_attachment_basic + primary_resource_id: attachment vars: - base_disk_name: 'my-base-disk' - snapshot_name: 'my-snapshot' - disk_name: 'my-disk' - policy_name: 'my-resource-policy' + base_disk_name: my-base-disk + disk_name: my-disk + policy_name: my-resource-policy + snapshot_name: my-snapshot parameters: - - name: 'disk' + - name: disk type: ResourceRef + required: true description: | The name of the regional disk in which the resource policies are attached to. url_param_only: true - required: true - resource: 'Disk' - imports: 'name' - - name: 'region' + resource: Disk + imports: name + - name: region type: ResourceRef - description: 'A reference to the region where the disk resides.' + description: A reference to the region where the disk resides. url_param_only: true - required: false + resource: Region + imports: name default_from_api: true - resource: 'Region' - imports: 'name' properties: - - name: 'name' + - name: name type: String + required: true description: | The resource policy to be attached to the disk for scheduling snapshot creation. Do not specify the self link. - required: true diff --git a/mmv1/products/compute/ResourcePolicyAttachment.yaml b/mmv1/products/compute/ResourcePolicyAttachment.yaml index c739b3171857..9d41f9a760c4 100644 --- a/mmv1/products/compute/ResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/ResourcePolicyAttachment.yaml @@ -12,7 +12,7 @@ # limitations under the License. --- -name: 'ResourcePolicyAttachment' +name: ResourcePolicyAttachment api_resource_type_kind: Instance description: | Adds existing resource policies to a compute instance. You can only add one policy @@ -21,25 +21,12 @@ description: | This resource can be used instead of setting the resource_policy directly in the compute instance resource to avoid dependency issues when using instance-level IAM permissions. -docs: -id_format: '{{project}}/{{zone}}/{{instance}}/{{name}}' -base_url: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}' -self_link: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}' -create_url: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}/addResourcePolicies' -delete_url: 'projects/{{project}}/zones/{{zone}}/instances/{{instance}}/removeResourcePolicies' -delete_verb: 'POST' +base_url: projects/{{project}}/zones/{{zone}}/instances/{{instance}} immutable: true -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -async: - actions: ['create', 'delete', 'update'] - type: 'OpAsync' - operation: - base_url: '{{op_id}}' - result: - resource_inside_response: false +self_link: projects/{{project}}/zones/{{zone}}/instances/{{instance}} +create_url: projects/{{project}}/zones/{{zone}}/instances/{{instance}}/addResourcePolicies +delete_url: projects/{{project}}/zones/{{zone}}/instances/{{instance}}/removeResourcePolicies +delete_verb: POST identity: - name nested_query: @@ -47,39 +34,41 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false -flatten_all_in_method: true +id_format: '{{project}}/{{zone}}/{{instance}}/{{name}}' +async: + operation: + base_url: '{{op_id}}' custom_code: - encoder: 'templates/terraform/encoders/compute_resource_policy_attachment.go.tmpl' - decoder: 'templates/terraform/decoders/compute_resource_policy_attachment.go.tmpl' - pre_delete: 'templates/terraform/pre_delete/compute_resource_policy_attachment.go.tmpl' + encoder: templates/terraform/encoders/compute_resource_policy_attachment.go.tmpl + decoder: templates/terraform/decoders/compute_resource_policy_attachment.go.tmpl + pre_delete: templates/terraform/pre_delete/compute_resource_policy_attachment.go.tmpl examples: - - name: 'compute_resource_policy_attachment_basic' - primary_resource_id: 'attachment' + - name: compute_resource_policy_attachment_basic + primary_resource_id: attachment vars: - instance_name: 'my-instance' - policy_name: 'my-resource-policy' + instance_name: my-instance + policy_name: my-resource-policy parameters: - - name: 'instance' + - name: instance type: ResourceRef + required: true description: | The name of the instance in which the resource policies are attached to. url_param_only: true - required: true - resource: 'Instance' - imports: 'name' - - name: 'zone' + resource: Instance + imports: name + - name: zone type: ResourceRef - description: 'A reference to the zone where the instance resides.' + description: A reference to the zone where the instance resides. url_param_only: true - required: false + resource: Zone + imports: name ignore_read: true default_from_api: true - resource: 'Zone' - imports: 'name' properties: - - name: 'name' + - name: name type: String + required: true description: | The resource policy to be attached to the instance for scheduling start/stop operations. Do not specify the self link. - required: true diff --git a/mmv1/products/kms/SecretCiphertext.yaml b/mmv1/products/kms/SecretCiphertext.yaml index ffe846689b78..f85549ea38b2 100644 --- a/mmv1/products/kms/SecretCiphertext.yaml +++ b/mmv1/products/kms/SecretCiphertext.yaml @@ -12,7 +12,7 @@ # limitations under the License. --- -name: 'SecretCiphertext' +name: SecretCiphertext api_resource_type_kind: CryptoKey description: | Encrypts secret data with Google Cloud KMS and provides access to the ciphertext. @@ -24,62 +24,56 @@ description: | data outside of resource definitions. references: guides: - 'Encrypting and decrypting data with a symmetric key': 'https://cloud.google.com/kms/docs/encrypt-decrypt' - api: 'https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt' -docs: -id_format: '{{crypto_key}}/{{ciphertext}}' + Encrypting and decrypting data with a symmetric key: https://cloud.google.com/kms/docs/encrypt-decrypt + api: https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys/encrypt base_url: '{{crypto_key}}' +immutable: true self_link: '{{crypto_key}}' create_url: '{{crypto_key}}:encrypt' -exclude_delete: true -immutable: true +id_format: '{{crypto_key}}/{{ciphertext}}' exclude_import: true -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -flatten_all_in_method: true -custom_code: - decoder: 'templates/terraform/decoders/noop.go.tmpl' - post_create: 'templates/terraform/post_create/kms_secret_ciphertext.go.tmpl' -exclude_tgc: true +exclude_delete: true supports_indirect_user_project_override: true +exclude_tgc: true +custom_code: + decoder: templates/terraform/decoders/noop.go.tmpl + post_create: templates/terraform/post_create/kms_secret_ciphertext.go.tmpl examples: - - name: 'kms_secret_ciphertext_basic' - primary_resource_id: 'my_password' - vars: - instance_name: 'my-instance' + - name: kms_secret_ciphertext_basic + primary_resource_id: my_password exclude_test: true + vars: + instance_name: my-instance parameters: - - name: 'cryptoKey' + - name: cryptoKey type: String + required: true description: | The full name of the CryptoKey that will be used to encrypt the provided plaintext. Format: `'projects/{{project}}/locations/{{location}}/keyRings/{{keyRing}}/cryptoKeys/{{cryptoKey}}'` url_param_only: true - required: true ignore_read: true properties: - - name: 'plaintext' + - name: plaintext type: String + required: true description: | The plaintext to be encrypted. - required: true - ignore_read: true sensitive: true - custom_expand: 'templates/terraform/custom_expand/base64.go.tmpl' - - name: 'additionalAuthenticatedData' + ignore_read: true + custom_expand: templates/terraform/custom_expand/base64.go.tmpl + - name: additionalAuthenticatedData type: String description: | The additional authenticated data used for integrity checks during encryption and decryption. - ignore_read: true sensitive: true - custom_expand: 'templates/terraform/custom_expand/base64.go.tmpl' - - name: 'ciphertext' + ignore_read: true + custom_expand: templates/terraform/custom_expand/base64.go.tmpl + - name: ciphertext type: String description: | Contains the result of encrypting the provided plaintext, encoded in base64. - ignore_read: true output: true + ignore_read: true validation: - function: 'verify.ValidateBase64String' + function: verify.ValidateBase64String From 96900e7b36cfebf334badd8929898923903f717e Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Sat, 21 Feb 2026 12:14:43 -0800 Subject: [PATCH 009/100] DomainMapping revert --- mmv1/products/cloudrun/DomainMapping.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 981e80b12372..9c3aa87e6ac8 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -27,6 +27,14 @@ import_format: - locations/{{location}}/namespaces/{{project}}/domainmappings/{{name}} custom_diff: - hasMetadata +async: + type: PollAsync + actions: + - create + - update + check_response_func_existence: PollCheckKnativeStatusFunc(res) + check_response_func_absence: transport_tpg.PollCheckForAbsence + target_occurrences: 1 error_retry_predicates: - transport_tpg.IsCloudRunCreationConflict schema_version: 1 From 2d22d1263c1f43fa24c3abbf264b5e4cca478153 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Sat, 21 Feb 2026 12:19:39 -0800 Subject: [PATCH 010/100] remove tgc_include_handwritten_tests --- mmv1/products/bigquery/Dataset.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 698674c9f1c4..ffb52e512405 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -38,7 +38,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true -tgc_include_handwritten_tests: true flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_dataset.go.tmpl' From a653f2f41099a170167ee0f9e946977f511bb7cb Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 23 Feb 2026 00:34:19 -0800 Subject: [PATCH 011/100] reduce the flatten_in_all_method in decoders to half --- mmv1/products/activedirectory/DomainTrust.yaml | 1 - mmv1/products/apigee/DeveloperApp.yaml | 1 - mmv1/products/apigee/EnvironmentAddonsConfig.yaml | 1 - mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml | 1 - mmv1/products/apigee/NatAddress.yaml | 1 - mmv1/products/appengine/DomainMapping.yaml | 1 - mmv1/products/backupdr/BackupPlan.yaml | 1 - mmv1/products/bigquery/Dataset.yaml | 1 - mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml | 1 - mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml | 1 - mmv1/products/bigquerydatatransfer/Config.yaml | 1 - mmv1/products/cloudasset/FolderFeed.yaml | 1 - mmv1/products/cloudasset/OrganizationFeed.yaml | 1 - mmv1/products/cloudrun/Service.yaml | 1 - mmv1/products/compute/DiskResourcePolicyAttachment.yaml | 1 - mmv1/products/compute/FirewallPolicyWithRules.yaml | 1 - mmv1/products/compute/GlobalNetworkEndpoint.yaml | 1 - mmv1/products/compute/Instance.yaml | 1 - mmv1/products/compute/NetworkEndpoint.yaml | 1 - mmv1/products/compute/NetworkEndpoints.yaml | 1 - mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml | 1 - mmv1/products/compute/RegionNetworkEndpoint.yaml | 1 - mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml | 1 - mmv1/products/compute/RouterRoutePolicy.yaml | 1 - 24 files changed, 24 deletions(-) diff --git a/mmv1/products/activedirectory/DomainTrust.yaml b/mmv1/products/activedirectory/DomainTrust.yaml index ed54fcf8c984..93771ad0c432 100644 --- a/mmv1/products/activedirectory/DomainTrust.yaml +++ b/mmv1/products/activedirectory/DomainTrust.yaml @@ -51,7 +51,6 @@ nested_query: - trusts is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/active_directory_domain_trust.go.tmpl' update_encoder: 'templates/terraform/update_encoder/active_directory_domain_trust.go.tmpl' diff --git a/mmv1/products/apigee/DeveloperApp.yaml b/mmv1/products/apigee/DeveloperApp.yaml index 55b07513f3bb..de66238ac526 100644 --- a/mmv1/products/apigee/DeveloperApp.yaml +++ b/mmv1/products/apigee/DeveloperApp.yaml @@ -29,7 +29,6 @@ update_mask: false update_verb: "PUT" import_format: - "{{org_id}}/developers/{{developer_email}}/apps/{{name}}" -flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/apigee_developer_app.go.tmpl" custom_import: "templates/terraform/custom_import/apigee_developer_app.go.tmpl" diff --git a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml index e640c4947492..972482ae7432 100644 --- a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml +++ b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml @@ -37,7 +37,6 @@ async: import_format: - '{{env_id}}' id_format: '{{env_id}}' -flatten_all_in_method: true custom_code: custom_import: 'templates/terraform/custom_import/apigee_env_addons.go.tmpl' decoder: 'templates/terraform/decoders/apigee_env_addons.go.tmpl' diff --git a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml index bdc8a878ec5b..938d328a6a92 100644 --- a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml +++ b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml @@ -34,7 +34,6 @@ timeouts: update_minutes: 20 delete_minutes: 1 autogen_async: true -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/apigee_environment_keyvaluemaps.go.tmpl' custom_create: 'templates/terraform/custom_create/apigee_environment_keyvaluemaps.go.tmpl' diff --git a/mmv1/products/apigee/NatAddress.yaml b/mmv1/products/apigee/NatAddress.yaml index 3ab99203e109..916e33d2be46 100644 --- a/mmv1/products/apigee/NatAddress.yaml +++ b/mmv1/products/apigee/NatAddress.yaml @@ -40,7 +40,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/apigee_nat_address.go.tmpl' encoder: 'templates/terraform/encoders/apigee_nat_address.go.tmpl' diff --git a/mmv1/products/appengine/DomainMapping.yaml b/mmv1/products/appengine/DomainMapping.yaml index 42234352b931..1e9995803021 100644 --- a/mmv1/products/appengine/DomainMapping.yaml +++ b/mmv1/products/appengine/DomainMapping.yaml @@ -39,7 +39,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/app_engine_domain_mapping.go.tmpl' examples: diff --git a/mmv1/products/backupdr/BackupPlan.yaml b/mmv1/products/backupdr/BackupPlan.yaml index 3aec2d94f787..39cccd01c1d7 100644 --- a/mmv1/products/backupdr/BackupPlan.yaml +++ b/mmv1/products/backupdr/BackupPlan.yaml @@ -29,7 +29,6 @@ timeouts: insert_minutes: 60 update_minutes: 60 delete_minutes: 60 -flatten_all_in_method: true custom_code: tgc_decoder: 'templates/tgc_next/decoders/backup_dr_backup_plan.go.tmpl' include_in_tgc_next: true diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index ffb52e512405..5d389755f6c4 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -38,7 +38,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_dataset.go.tmpl' pre_read: 'templates/terraform/pre_read/bigquery_dataset.go.tmpl' diff --git a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml index 69a1c860d173..bc965f172b43 100644 --- a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml @@ -29,7 +29,6 @@ self_link: 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscrip create_url: 'projects/{{data_exchange_project}}/locations/{{data_exchange_location}}/dataExchanges/{{data_exchange_id}}:subscribe' import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' encoder: 'templates/terraform/encoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' diff --git a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml index 48b6ae02f804..e9b68a3ee1c9 100644 --- a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml @@ -29,7 +29,6 @@ create_url: 'projects/{{project}}/locations/{{location}}/dataExchanges/{{data_ex immutable: true import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' -flatten_all_in_method: true custom_code: constants: templates/terraform/constants/bigqueryanalyticshub_listing_subscription.go.tmpl decoder: 'templates/terraform/decoders/bigqueryanalyticshub_listing_subscription.go.tmpl' diff --git a/mmv1/products/bigquerydatatransfer/Config.yaml b/mmv1/products/bigquerydatatransfer/Config.yaml index c8b0608a32ec..b7aef36e1dbb 100644 --- a/mmv1/products/bigquerydatatransfer/Config.yaml +++ b/mmv1/products/bigquerydatatransfer/Config.yaml @@ -34,7 +34,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_data_transfer.go.tmpl' encoder: 'templates/terraform/encoders/bigquery_data_transfer.go.tmpl' diff --git a/mmv1/products/cloudasset/FolderFeed.yaml b/mmv1/products/cloudasset/FolderFeed.yaml index 5d6e4530b269..483ae1c4cb3c 100644 --- a/mmv1/products/cloudasset/FolderFeed.yaml +++ b/mmv1/products/cloudasset/FolderFeed.yaml @@ -33,7 +33,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 collection_url_key: 'feeds' -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/cloud_asset_feed.go.tmpl' pre_create: 'templates/terraform/pre_create/cloud_asset_feed.go.tmpl' diff --git a/mmv1/products/cloudasset/OrganizationFeed.yaml b/mmv1/products/cloudasset/OrganizationFeed.yaml index e47ec3abbeba..b6bc05e7677d 100644 --- a/mmv1/products/cloudasset/OrganizationFeed.yaml +++ b/mmv1/products/cloudasset/OrganizationFeed.yaml @@ -33,7 +33,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 collection_url_key: 'feeds' -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/cloud_asset_feed.go.tmpl' pre_create: 'templates/terraform/pre_create/cloud_asset_feed.go.tmpl' diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index fe5e906f21f8..6f8fe3a5cadc 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -51,7 +51,6 @@ iam_policy: import_format: - 'projects/{{project}}/locations/{{location}}/services/{{service}}' - '{{service}}' -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/cloud_run_service.go.tmpl' encoder: 'templates/terraform/encoders/cloud_run_service.go.tmpl' diff --git a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml index f5dba0b2553d..eba8c82256b6 100644 --- a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml @@ -45,7 +45,6 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_disk_resource_policies_attachment.go.tmpl' decoder: 'templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl' diff --git a/mmv1/products/compute/FirewallPolicyWithRules.yaml b/mmv1/products/compute/FirewallPolicyWithRules.yaml index 96a50146221c..736a927304dc 100644 --- a/mmv1/products/compute/FirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/FirewallPolicyWithRules.yaml @@ -29,7 +29,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/GlobalNetworkEndpoint.yaml b/mmv1/products/compute/GlobalNetworkEndpoint.yaml index 06a6a3a02faf..740696cb9e60 100644 --- a/mmv1/products/compute/GlobalNetworkEndpoint.yaml +++ b/mmv1/products/compute/GlobalNetworkEndpoint.yaml @@ -53,7 +53,6 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_global_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/Instance.yaml b/mmv1/products/compute/Instance.yaml index f1a6acadb180..193b3cc410dd 100644 --- a/mmv1/products/compute/Instance.yaml +++ b/mmv1/products/compute/Instance.yaml @@ -37,7 +37,6 @@ iam_policy: allowed_iam_role: 'roles/compute.osLogin' parent_resource_attribute: 'instance_name' iam_conditions_request_type: 'QUERY_PARAM' -flatten_all_in_method: true custom_code: examples: - name: 'instance_basic' diff --git a/mmv1/products/compute/NetworkEndpoint.yaml b/mmv1/products/compute/NetworkEndpoint.yaml index 11b29e0126fc..67b16dc943d7 100644 --- a/mmv1/products/compute/NetworkEndpoint.yaml +++ b/mmv1/products/compute/NetworkEndpoint.yaml @@ -59,7 +59,6 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/unwrap_resource.go.tmpl' diff --git a/mmv1/products/compute/NetworkEndpoints.yaml b/mmv1/products/compute/NetworkEndpoints.yaml index 37edf62b0647..4bc74355c5b1 100644 --- a/mmv1/products/compute/NetworkEndpoints.yaml +++ b/mmv1/products/compute/NetworkEndpoints.yaml @@ -58,7 +58,6 @@ async: resource_inside_response: false identity: - networkEndpointGroup -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/network_endpoints.go.tmpl' encoder: 'templates/terraform/encoders/compute_network_endpoints.go.tmpl' diff --git a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml index a7b86a90683d..f82f8c7981af 100644 --- a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml @@ -31,7 +31,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RegionNetworkEndpoint.yaml b/mmv1/products/compute/RegionNetworkEndpoint.yaml index 37da1a094851..979a9d3126e7 100644 --- a/mmv1/products/compute/RegionNetworkEndpoint.yaml +++ b/mmv1/products/compute/RegionNetworkEndpoint.yaml @@ -55,7 +55,6 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_region_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml index 36777743df96..3690677e0024 100644 --- a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml @@ -31,7 +31,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RouterRoutePolicy.yaml b/mmv1/products/compute/RouterRoutePolicy.yaml index adf91fc1726f..0d4dd3bc8069 100644 --- a/mmv1/products/compute/RouterRoutePolicy.yaml +++ b/mmv1/products/compute/RouterRoutePolicy.yaml @@ -42,7 +42,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/unwrap_route_policy_resource.go.tmpl' examples: From 9dafa16de9003113e35f65b7145075f72c32d54c Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 23 Feb 2026 14:14:17 -0800 Subject: [PATCH 012/100] remove flatten_all on resources producing a interaction not found error --- mmv1/products/healthcare/Dataset.yaml | 1 - mmv1/products/healthcare/DicomStore.yaml | 1 - mmv1/products/healthcare/FhirStore.yaml | 1 - mmv1/products/healthcare/Hl7V2Store.yaml | 1 - mmv1/products/healthcare/PipelineJob.yaml | 1 - mmv1/products/monitoring/MonitoredProject.yaml | 1 - mmv1/products/spanner/BackupSchedule.yaml | 1 - mmv1/products/spanner/Database.yaml | 1 - mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml | 1 - 9 files changed, 9 deletions(-) diff --git a/mmv1/products/healthcare/Dataset.yaml b/mmv1/products/healthcare/Dataset.yaml index 6e53ef81e584..d8313d98ba65 100644 --- a/mmv1/products/healthcare/Dataset.yaml +++ b/mmv1/products/healthcare/Dataset.yaml @@ -32,7 +32,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' error_retry_predicates: diff --git a/mmv1/products/healthcare/DicomStore.yaml b/mmv1/products/healthcare/DicomStore.yaml index 8409bf02ae5e..2e2c9b448e33 100644 --- a/mmv1/products/healthcare/DicomStore.yaml +++ b/mmv1/products/healthcare/DicomStore.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_dicom_store.go.tmpl' diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index 660786dd4786..e8d5fcdcd9b2 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_fhir_store.go.tmpl' diff --git a/mmv1/products/healthcare/Hl7V2Store.yaml b/mmv1/products/healthcare/Hl7V2Store.yaml index b5a076b7a476..c2bea16e4880 100644 --- a/mmv1/products/healthcare/Hl7V2Store.yaml +++ b/mmv1/products/healthcare/Hl7V2Store.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_hl7_v2_store.go.tmpl' diff --git a/mmv1/products/healthcare/PipelineJob.yaml b/mmv1/products/healthcare/PipelineJob.yaml index b2fae67c1dda..260f4380a098 100644 --- a/mmv1/products/healthcare/PipelineJob.yaml +++ b/mmv1/products/healthcare/PipelineJob.yaml @@ -71,7 +71,6 @@ examples: source_fhirstore_name: 'source_fhir_store' dest_fhirstore_name: 'dest_fhir_store' bucket_name: 'example_bucket_name' -flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/long_name_to_self_link.go.tmpl parameters: diff --git a/mmv1/products/monitoring/MonitoredProject.yaml b/mmv1/products/monitoring/MonitoredProject.yaml index 891bb5c83036..8380e7b3dc1d 100644 --- a/mmv1/products/monitoring/MonitoredProject.yaml +++ b/mmv1/products/monitoring/MonitoredProject.yaml @@ -34,7 +34,6 @@ async: actions: ['create', 'delete'] operation: base_url: '{{op_id}}' -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/monitoring_monitored_project.go.tmpl' test_constants: 'templates/terraform/test_constants/monitoring_monitored_project.go.tmpl' diff --git a/mmv1/products/spanner/BackupSchedule.yaml b/mmv1/products/spanner/BackupSchedule.yaml index 3a0e4598a6f7..485c6f739bac 100644 --- a/mmv1/products/spanner/BackupSchedule.yaml +++ b/mmv1/products/spanner/BackupSchedule.yaml @@ -41,7 +41,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/spanner_schedule_backup.go.tmpl' decoder: 'templates/terraform/decoders/spanner_schedule_backup.go.tmpl' diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index dd99b1016c43..a8e189ed4bde 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -51,7 +51,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_database.go.tmpl' encoder: 'templates/terraform/encoders/spanner_database.go.tmpl' diff --git a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml index fdcd37c7dfc2..9692370bf120 100644 --- a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml +++ b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml @@ -46,7 +46,6 @@ async: result: resource_inside_response: true include_project: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/vertex_ai_index_endpoint_deployed_index.go.tmpl' update_encoder: 'templates/terraform/update_encoder/vertex_ai_index_endpoint_deployed_index.go.tmpl' From 1709e16e1abd684dffe4b211d81400dd67d86fb9 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 23 Feb 2026 21:10:34 -0800 Subject: [PATCH 013/100] remove flatten_all_method from cryptoKey --- mmv1/products/kms/CryptoKey.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/products/kms/CryptoKey.yaml b/mmv1/products/kms/CryptoKey.yaml index 0b9d2d2b966c..2df23c9526ad 100644 --- a/mmv1/products/kms/CryptoKey.yaml +++ b/mmv1/products/kms/CryptoKey.yaml @@ -36,7 +36,6 @@ self_link: '{{key_ring}}/cryptoKeys/{{name}}' create_url: '{{key_ring}}/cryptoKeys?cryptoKeyId={{name}}&skipInitialVersionCreation={{skip_initial_version_creation}}' update_verb: 'PATCH' update_mask: true -flatten_all_in_method: true import_format: - '{{key_ring}}/cryptoKeys/{{name}}' include_in_tgc_next: true From ae1ec0dc0db1a449867cf9d4f5968148d859df45 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 23 Feb 2026 21:11:02 -0800 Subject: [PATCH 014/100] remove flatten_all_method from keyRing --- mmv1/products/kms/KeyRing.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/products/kms/KeyRing.yaml b/mmv1/products/kms/KeyRing.yaml index 2165f2448cb0..6cca3351f8a0 100644 --- a/mmv1/products/kms/KeyRing.yaml +++ b/mmv1/products/kms/KeyRing.yaml @@ -38,7 +38,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: tgc_ignore_terraform_decoder: true encoder: 'templates/terraform/encoders/send_nil_body.go.tmpl' From cad8f60ed0918e2515e94cae776f9e5f62b6c6df Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 25 Feb 2026 13:29:00 -0800 Subject: [PATCH 015/100] Revert "remove flatten_all on resources producing a interaction not found error" This reverts commit 6153af83eff6174eb174193019c5bde4ecc52f42. --- mmv1/products/healthcare/Dataset.yaml | 1 + mmv1/products/healthcare/DicomStore.yaml | 1 + mmv1/products/healthcare/FhirStore.yaml | 1 + mmv1/products/healthcare/Hl7V2Store.yaml | 1 + mmv1/products/healthcare/PipelineJob.yaml | 1 + mmv1/products/monitoring/MonitoredProject.yaml | 1 + mmv1/products/spanner/BackupSchedule.yaml | 1 + mmv1/products/spanner/Database.yaml | 1 + mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml | 1 + 9 files changed, 9 insertions(+) diff --git a/mmv1/products/healthcare/Dataset.yaml b/mmv1/products/healthcare/Dataset.yaml index d8313d98ba65..6e53ef81e584 100644 --- a/mmv1/products/healthcare/Dataset.yaml +++ b/mmv1/products/healthcare/Dataset.yaml @@ -32,6 +32,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' error_retry_predicates: diff --git a/mmv1/products/healthcare/DicomStore.yaml b/mmv1/products/healthcare/DicomStore.yaml index 2e2c9b448e33..8409bf02ae5e 100644 --- a/mmv1/products/healthcare/DicomStore.yaml +++ b/mmv1/products/healthcare/DicomStore.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_dicom_store.go.tmpl' diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index e8d5fcdcd9b2..660786dd4786 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_fhir_store.go.tmpl' diff --git a/mmv1/products/healthcare/Hl7V2Store.yaml b/mmv1/products/healthcare/Hl7V2Store.yaml index c2bea16e4880..b5a076b7a476 100644 --- a/mmv1/products/healthcare/Hl7V2Store.yaml +++ b/mmv1/products/healthcare/Hl7V2Store.yaml @@ -33,6 +33,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_hl7_v2_store.go.tmpl' diff --git a/mmv1/products/healthcare/PipelineJob.yaml b/mmv1/products/healthcare/PipelineJob.yaml index 260f4380a098..b2fae67c1dda 100644 --- a/mmv1/products/healthcare/PipelineJob.yaml +++ b/mmv1/products/healthcare/PipelineJob.yaml @@ -71,6 +71,7 @@ examples: source_fhirstore_name: 'source_fhir_store' dest_fhirstore_name: 'dest_fhir_store' bucket_name: 'example_bucket_name' +flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/long_name_to_self_link.go.tmpl parameters: diff --git a/mmv1/products/monitoring/MonitoredProject.yaml b/mmv1/products/monitoring/MonitoredProject.yaml index 8380e7b3dc1d..891bb5c83036 100644 --- a/mmv1/products/monitoring/MonitoredProject.yaml +++ b/mmv1/products/monitoring/MonitoredProject.yaml @@ -34,6 +34,7 @@ async: actions: ['create', 'delete'] operation: base_url: '{{op_id}}' +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/monitoring_monitored_project.go.tmpl' test_constants: 'templates/terraform/test_constants/monitoring_monitored_project.go.tmpl' diff --git a/mmv1/products/spanner/BackupSchedule.yaml b/mmv1/products/spanner/BackupSchedule.yaml index 485c6f739bac..3a0e4598a6f7 100644 --- a/mmv1/products/spanner/BackupSchedule.yaml +++ b/mmv1/products/spanner/BackupSchedule.yaml @@ -41,6 +41,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/spanner_schedule_backup.go.tmpl' decoder: 'templates/terraform/decoders/spanner_schedule_backup.go.tmpl' diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index a8e189ed4bde..dd99b1016c43 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -51,6 +51,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_database.go.tmpl' encoder: 'templates/terraform/encoders/spanner_database.go.tmpl' diff --git a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml index 9692370bf120..fdcd37c7dfc2 100644 --- a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml +++ b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml @@ -46,6 +46,7 @@ async: result: resource_inside_response: true include_project: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/vertex_ai_index_endpoint_deployed_index.go.tmpl' update_encoder: 'templates/terraform/update_encoder/vertex_ai_index_endpoint_deployed_index.go.tmpl' From 4bbdfe05f5af3fef114c6fdcf945f364eeaff942 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:21:22 -0700 Subject: [PATCH 016/100] resolve post merge conflicts --- mmv1/products/sql/SourceRepresentationInstance.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mmv1/products/sql/SourceRepresentationInstance.yaml b/mmv1/products/sql/SourceRepresentationInstance.yaml index 77fa167baa41..ae043a08c6b1 100644 --- a/mmv1/products/sql/SourceRepresentationInstance.yaml +++ b/mmv1/products/sql/SourceRepresentationInstance.yaml @@ -29,12 +29,6 @@ sweeper: field: settings.deletionProtectionEnabled value: "false" include_full_resource: true -async: - operation: - base_url: projects/{{project}}/operations/{{op_id}} -custom_code: - encoder: templates/terraform/encoders/sql_source_representation_instance.go.tmpl - decoder: templates/terraform/decoders/sql_source_representation_instance.go.tmpl examples: - name: sql_source_representation_instance_basic primary_resource_id: instance From 8e888238caa56b5a90f4d5cd3a610f3b45790106 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:34:59 -0700 Subject: [PATCH 017/100] enable flatten_all_in_method on Decoder+HasSelfLink+FlattenObject resources --- mmv1/products/compute/BackendService.yaml | 1 + mmv1/products/compute/Network.yaml | 1 + mmv1/products/compute/RegionBackendService.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/mmv1/products/compute/BackendService.yaml b/mmv1/products/compute/BackendService.yaml index 917edfab2323..058ed39167ee 100644 --- a/mmv1/products/compute/BackendService.yaml +++ b/mmv1/products/compute/BackendService.yaml @@ -52,6 +52,7 @@ include_in_tgc_next: true tgc_tests: - name: 'TestAccComputeBackendService_backendServiceCustomMetrics_update' skip: 'Test framework problem with single vs multiple block parsing of custom_metrics' +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/backend_service.go.tmpl' encoder: 'templates/terraform/encoders/backend_service.go.tmpl' diff --git a/mmv1/products/compute/Network.yaml b/mmv1/products/compute/Network.yaml index 3eb25579fa14..465e8df8812c 100644 --- a/mmv1/products/compute/Network.yaml +++ b/mmv1/products/compute/Network.yaml @@ -42,6 +42,7 @@ sweeper: # - "google_network_security_intercept_deployment_group" (beta only) - "google_network_security_firewall_endpoint_association" include_in_tgc_next: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_network.go.tmpl' update_encoder: 'templates/terraform/update_encoder/compute_network.go.tmpl' diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index 057fa35c3194..174c65387673 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -47,6 +47,7 @@ iam_policy: iam_conditions_request_type: 'QUERY_PARAM' min_version: 'beta' include_in_tgc_next: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/region_backend_service.go.tmpl' encoder: 'templates/terraform/encoders/region_backend_service.go.tmpl' From 780d7cf137228085eb4930a4151a5351ea4503b7 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:08 -0700 Subject: [PATCH 018/100] enable flatten_all_in_method on Decoder+HasSelfLink resources --- mmv1/products/compute/RegionTargetHttpsProxy.yaml | 1 + mmv1/products/compute/Route.yaml | 1 + mmv1/products/compute/Snapshot.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/mmv1/products/compute/RegionTargetHttpsProxy.yaml b/mmv1/products/compute/RegionTargetHttpsProxy.yaml index 556287dcac6b..9f4da8c9e3ca 100644 --- a/mmv1/products/compute/RegionTargetHttpsProxy.yaml +++ b/mmv1/products/compute/RegionTargetHttpsProxy.yaml @@ -37,6 +37,7 @@ async: result: resource_inside_response: false include_in_tgc_next: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_region_target_https_proxy.go.tmpl' # update_encoder is usually the same as encoder by default. This resource is an uncommon case where the whole resource diff --git a/mmv1/products/compute/Route.yaml b/mmv1/products/compute/Route.yaml index 2ca914168299..010cda564696 100644 --- a/mmv1/products/compute/Route.yaml +++ b/mmv1/products/compute/Route.yaml @@ -65,6 +65,7 @@ async: resource_inside_response: false collection_url_key: 'items' include_in_tgc_next: true +flatten_all_in_method: true custom_code: extra_schema_entry: 'templates/terraform/extra_schema_entry/route.tmpl' constants: 'templates/terraform/constants/compute_route.go.tmpl' diff --git a/mmv1/products/compute/Snapshot.yaml b/mmv1/products/compute/Snapshot.yaml index 7ebc4b6f4280..81dee719ea9d 100644 --- a/mmv1/products/compute/Snapshot.yaml +++ b/mmv1/products/compute/Snapshot.yaml @@ -55,6 +55,7 @@ iam_policy: - 'projects/{{project}}/global/snapshots/{{name}}' - '{{name}}' include_in_tgc_next: true +flatten_all_in_method: true custom_code: tgc_decoder: 'templates/tgc_next/decoders/compute_snapshot.go.tmpl' decoder: 'templates/terraform/decoders/snapshot.go.tmpl' From b288b3c17816b91189038001338e2bef36a3f7eb Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:13 -0700 Subject: [PATCH 019/100] enable flatten_all_in_method on Decoder+NestedQuery resources --- mmv1/products/activedirectory/DomainTrust.yaml | 1 + mmv1/products/compute/DiskResourcePolicyAttachment.yaml | 1 + mmv1/products/compute/GlobalNetworkEndpoint.yaml | 1 + mmv1/products/compute/NetworkEndpoint.yaml | 1 + mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml | 1 + mmv1/products/compute/RegionNetworkEndpoint.yaml | 1 + mmv1/products/compute/ResourcePolicyAttachment.yaml | 1 + 7 files changed, 7 insertions(+) diff --git a/mmv1/products/activedirectory/DomainTrust.yaml b/mmv1/products/activedirectory/DomainTrust.yaml index 93771ad0c432..ed54fcf8c984 100644 --- a/mmv1/products/activedirectory/DomainTrust.yaml +++ b/mmv1/products/activedirectory/DomainTrust.yaml @@ -51,6 +51,7 @@ nested_query: - trusts is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/active_directory_domain_trust.go.tmpl' update_encoder: 'templates/terraform/update_encoder/active_directory_domain_trust.go.tmpl' diff --git a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml index eba8c82256b6..f5dba0b2553d 100644 --- a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml @@ -45,6 +45,7 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_disk_resource_policies_attachment.go.tmpl' decoder: 'templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl' diff --git a/mmv1/products/compute/GlobalNetworkEndpoint.yaml b/mmv1/products/compute/GlobalNetworkEndpoint.yaml index 740696cb9e60..06a6a3a02faf 100644 --- a/mmv1/products/compute/GlobalNetworkEndpoint.yaml +++ b/mmv1/products/compute/GlobalNetworkEndpoint.yaml @@ -53,6 +53,7 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_global_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/NetworkEndpoint.yaml b/mmv1/products/compute/NetworkEndpoint.yaml index 67b16dc943d7..11b29e0126fc 100644 --- a/mmv1/products/compute/NetworkEndpoint.yaml +++ b/mmv1/products/compute/NetworkEndpoint.yaml @@ -59,6 +59,7 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/unwrap_resource.go.tmpl' diff --git a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml index aa47a8ff28ab..8778b2734084 100644 --- a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml @@ -36,6 +36,7 @@ id_format: '{{project}}/{{region}}/{{disk}}/{{name}}' async: operation: base_url: '{{op_id}}' +flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/compute_region_disk_resource_policies_attachment.go.tmpl decoder: templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl diff --git a/mmv1/products/compute/RegionNetworkEndpoint.yaml b/mmv1/products/compute/RegionNetworkEndpoint.yaml index 979a9d3126e7..37da1a094851 100644 --- a/mmv1/products/compute/RegionNetworkEndpoint.yaml +++ b/mmv1/products/compute/RegionNetworkEndpoint.yaml @@ -55,6 +55,7 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_region_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/ResourcePolicyAttachment.yaml b/mmv1/products/compute/ResourcePolicyAttachment.yaml index 9d41f9a760c4..2ae9f3b7ddf5 100644 --- a/mmv1/products/compute/ResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/ResourcePolicyAttachment.yaml @@ -38,6 +38,7 @@ id_format: '{{project}}/{{zone}}/{{instance}}/{{name}}' async: operation: base_url: '{{op_id}}' +flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/compute_resource_policy_attachment.go.tmpl decoder: templates/terraform/decoders/compute_resource_policy_attachment.go.tmpl From cbeae2e699b162315bfebda5e9ae47b23cef6ea2 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:24 -0700 Subject: [PATCH 020/100] enable flatten_all_in_method on PostRead+NestedQuery resources --- .../accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml | 1 + .../ServicePerimeterDryRunIngressPolicy.yaml | 1 + .../accesscontextmanager/ServicePerimeterDryRunResource.yaml | 1 + .../accesscontextmanager/ServicePerimeterEgressPolicy.yaml | 1 + .../accesscontextmanager/ServicePerimeterIngressPolicy.yaml | 1 + 5 files changed, 5 insertions(+) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml index 606f6021a50d..7883b192b5be 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml @@ -69,6 +69,7 @@ nested_query: - egressPolicies is_list_of_ids: false modify_by_patch: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_dry_run_egress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml index 4675d4196ef4..7bbfbfbca059 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml @@ -70,6 +70,7 @@ nested_query: - ingressPolicies is_list_of_ids: false modify_by_patch: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_dry_run_egress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml index 54f3fb892503..31619351f6ef 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml @@ -66,6 +66,7 @@ nested_query: - resources is_list_of_ids: true modify_by_patch: true +flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_dry_run_resource.go.tmpl' pre_create: 'templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index d68a16a4515d..a34be5c21280 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -69,6 +69,7 @@ nested_query: - egressPolicies is_list_of_ids: false modify_by_patch: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' custom_import: 'templates/terraform/custom_import/access_context_manager_service_perimeter_egress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 8eaff084e78d..da6f095daed0 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -70,6 +70,7 @@ nested_query: - ingressPolicies is_list_of_ids: false modify_by_patch: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' custom_import: 'templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.tmpl' From e47af8e59f2313a63624e736226b317c88fe34d5 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:29 -0700 Subject: [PATCH 021/100] enable flatten_all_in_method on Decoder+PostRead+HasSelfLink resources --- mmv1/products/compute/Disk.yaml | 1 + mmv1/products/compute/RegionDisk.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index 745344fd2f6f..f3b5fe09233e 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -57,6 +57,7 @@ iam_policy: - 'projects/{{project}}/zones/{{zone}}/disks/{{name}}' - '{{name}}' include_in_tgc_next: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/disk.tmpl' encoder: 'templates/terraform/encoders/disk.tmpl' diff --git a/mmv1/products/compute/RegionDisk.yaml b/mmv1/products/compute/RegionDisk.yaml index c34dd4dd4ed5..24b0cef69fc7 100644 --- a/mmv1/products/compute/RegionDisk.yaml +++ b/mmv1/products/compute/RegionDisk.yaml @@ -59,6 +59,7 @@ iam_policy: - 'projects/{{project}}/regions/{{region}}/disks/{{name}}' - '{{name}}' include_in_tgc_next: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/region_disk.go.tmpl' encoder: 'templates/terraform/encoders/disk.tmpl' From f3cfbf906a124ad3eb67905b405ff3f675a23c23 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:33 -0700 Subject: [PATCH 022/100] enable flatten_all_in_method on Decoder+PostRead resources --- mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml | 1 + mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml index bc965f172b43..69a1c860d173 100644 --- a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml @@ -29,6 +29,7 @@ self_link: 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscrip create_url: 'projects/{{data_exchange_project}}/locations/{{data_exchange_location}}/dataExchanges/{{data_exchange_id}}:subscribe' import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' encoder: 'templates/terraform/encoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' diff --git a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml index e9b68a3ee1c9..48b6ae02f804 100644 --- a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml @@ -29,6 +29,7 @@ create_url: 'projects/{{project}}/locations/{{location}}/dataExchanges/{{data_ex immutable: true import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' +flatten_all_in_method: true custom_code: constants: templates/terraform/constants/bigqueryanalyticshub_listing_subscription.go.tmpl decoder: 'templates/terraform/decoders/bigqueryanalyticshub_listing_subscription.go.tmpl' From 8eadcbd0a0e8435879a2f773e0336cabf9501ead Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:38 -0700 Subject: [PATCH 023/100] enable flatten_all_in_method on Decoder+FlattenObject resources --- mmv1/products/cloudrun/Service.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 6f8fe3a5cadc..fe5e906f21f8 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -51,6 +51,7 @@ iam_policy: import_format: - 'projects/{{project}}/locations/{{location}}/services/{{service}}' - '{{service}}' +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/cloud_run_service.go.tmpl' encoder: 'templates/terraform/encoders/cloud_run_service.go.tmpl' From 6bd6fd5f9ae886f53e47e4fa9c3236e5c43f7df5 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 16:35:43 -0700 Subject: [PATCH 024/100] enable flatten_all_in_method on remaining decoder-only resources --- mmv1/products/apigee/DeveloperApp.yaml | 1 + mmv1/products/apigee/EnvironmentAddonsConfig.yaml | 1 + mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml | 1 + mmv1/products/apigee/NatAddress.yaml | 1 + mmv1/products/appengine/DomainMapping.yaml | 1 + mmv1/products/bigquerydatatransfer/Config.yaml | 1 + mmv1/products/chronicle/DashboardChart.yaml | 1 + mmv1/products/cloudbilling/ProjectInfo.yaml | 1 + mmv1/products/cloudrun/DomainMapping.yaml | 1 + mmv1/products/compute/FirewallPolicyWithRules.yaml | 1 + mmv1/products/compute/NetworkEndpoints.yaml | 1 + mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml | 1 + mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml | 1 + mmv1/products/compute/RouterRoutePolicy.yaml | 1 + mmv1/products/dataplex/EntryLink.yaml | 1 + mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml | 1 + mmv1/products/kms/SecretCiphertext.yaml | 1 + mmv1/products/osconfig/PatchDeployment.yaml | 1 + 18 files changed, 18 insertions(+) diff --git a/mmv1/products/apigee/DeveloperApp.yaml b/mmv1/products/apigee/DeveloperApp.yaml index de66238ac526..55b07513f3bb 100644 --- a/mmv1/products/apigee/DeveloperApp.yaml +++ b/mmv1/products/apigee/DeveloperApp.yaml @@ -29,6 +29,7 @@ update_mask: false update_verb: "PUT" import_format: - "{{org_id}}/developers/{{developer_email}}/apps/{{name}}" +flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/apigee_developer_app.go.tmpl" custom_import: "templates/terraform/custom_import/apigee_developer_app.go.tmpl" diff --git a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml index 972482ae7432..e640c4947492 100644 --- a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml +++ b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml @@ -37,6 +37,7 @@ async: import_format: - '{{env_id}}' id_format: '{{env_id}}' +flatten_all_in_method: true custom_code: custom_import: 'templates/terraform/custom_import/apigee_env_addons.go.tmpl' decoder: 'templates/terraform/decoders/apigee_env_addons.go.tmpl' diff --git a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml index 938d328a6a92..bdc8a878ec5b 100644 --- a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml +++ b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml @@ -34,6 +34,7 @@ timeouts: update_minutes: 20 delete_minutes: 1 autogen_async: true +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/apigee_environment_keyvaluemaps.go.tmpl' custom_create: 'templates/terraform/custom_create/apigee_environment_keyvaluemaps.go.tmpl' diff --git a/mmv1/products/apigee/NatAddress.yaml b/mmv1/products/apigee/NatAddress.yaml index 916e33d2be46..3ab99203e109 100644 --- a/mmv1/products/apigee/NatAddress.yaml +++ b/mmv1/products/apigee/NatAddress.yaml @@ -40,6 +40,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/apigee_nat_address.go.tmpl' encoder: 'templates/terraform/encoders/apigee_nat_address.go.tmpl' diff --git a/mmv1/products/appengine/DomainMapping.yaml b/mmv1/products/appengine/DomainMapping.yaml index 1e9995803021..42234352b931 100644 --- a/mmv1/products/appengine/DomainMapping.yaml +++ b/mmv1/products/appengine/DomainMapping.yaml @@ -39,6 +39,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/app_engine_domain_mapping.go.tmpl' examples: diff --git a/mmv1/products/bigquerydatatransfer/Config.yaml b/mmv1/products/bigquerydatatransfer/Config.yaml index b7aef36e1dbb..c8b0608a32ec 100644 --- a/mmv1/products/bigquerydatatransfer/Config.yaml +++ b/mmv1/products/bigquerydatatransfer/Config.yaml @@ -34,6 +34,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_data_transfer.go.tmpl' encoder: 'templates/terraform/encoders/bigquery_data_transfer.go.tmpl' diff --git a/mmv1/products/chronicle/DashboardChart.yaml b/mmv1/products/chronicle/DashboardChart.yaml index d9bf0c3f81ba..76b4039b6859 100644 --- a/mmv1/products/chronicle/DashboardChart.yaml +++ b/mmv1/products/chronicle/DashboardChart.yaml @@ -34,6 +34,7 @@ delete_verb: POST import_format: - projects/{{project}}/locations/{{location}}/instances/{{instance}}/dashboardCharts/{{chart_id}} +flatten_all_in_method: true custom_code: pre_delete: "templates/terraform/pre_delete/chronicle_dashboard_chart.go.tmpl" pre_update: "templates/terraform/pre_update/chronicle_dashboard_chart_dashboard_query.go.tmpl" diff --git a/mmv1/products/cloudbilling/ProjectInfo.yaml b/mmv1/products/cloudbilling/ProjectInfo.yaml index b692332973cb..a85f317cffa0 100644 --- a/mmv1/products/cloudbilling/ProjectInfo.yaml +++ b/mmv1/products/cloudbilling/ProjectInfo.yaml @@ -28,6 +28,7 @@ import_format: - projects/{{%project}} - '{{%project}}' cai_asset_name_format: projects/{{project}}/billingInfo +flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/billing_project_info.go.tmpl decoder: templates/terraform/decoders/billing_project_info.go.tmpl diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 9c3aa87e6ac8..383845d24852 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -40,6 +40,7 @@ error_retry_predicates: schema_version: 1 state_upgraders: true cai_asset_name_format: projects/{{project}}/locations/{{location}}/domainmappings/{{name}} +flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/cloud_run_domain_mapping.go.tmpl decoder: templates/terraform/decoders/cloud_run.go.tmpl diff --git a/mmv1/products/compute/FirewallPolicyWithRules.yaml b/mmv1/products/compute/FirewallPolicyWithRules.yaml index 736a927304dc..96a50146221c 100644 --- a/mmv1/products/compute/FirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/FirewallPolicyWithRules.yaml @@ -29,6 +29,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/NetworkEndpoints.yaml b/mmv1/products/compute/NetworkEndpoints.yaml index 4bc74355c5b1..37edf62b0647 100644 --- a/mmv1/products/compute/NetworkEndpoints.yaml +++ b/mmv1/products/compute/NetworkEndpoints.yaml @@ -58,6 +58,7 @@ async: resource_inside_response: false identity: - networkEndpointGroup +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/network_endpoints.go.tmpl' encoder: 'templates/terraform/encoders/compute_network_endpoints.go.tmpl' diff --git a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml index f82f8c7981af..a7b86a90683d 100644 --- a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml @@ -31,6 +31,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml index 3690677e0024..36777743df96 100644 --- a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml @@ -31,6 +31,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RouterRoutePolicy.yaml b/mmv1/products/compute/RouterRoutePolicy.yaml index 0d4dd3bc8069..adf91fc1726f 100644 --- a/mmv1/products/compute/RouterRoutePolicy.yaml +++ b/mmv1/products/compute/RouterRoutePolicy.yaml @@ -42,6 +42,7 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false +flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/unwrap_route_policy_resource.go.tmpl' examples: diff --git a/mmv1/products/dataplex/EntryLink.yaml b/mmv1/products/dataplex/EntryLink.yaml index 5a5689464590..1943975ef43e 100644 --- a/mmv1/products/dataplex/EntryLink.yaml +++ b/mmv1/products/dataplex/EntryLink.yaml @@ -26,6 +26,7 @@ create_url: 'projects/{{project}}/locations/{{location}}/entryGroups/{{entry_gro update_verb: 'PATCH' import_format: - 'projects/{{project}}/locations/{{location}}/entryGroups/{{entry_group_id}}/entryLinks/{{entry_link_id}}' +flatten_all_in_method: true custom_code: constants: templates/terraform/constants/dataplex_entry_link.go.tmpl decoder: templates/terraform/decoders/dataplex_entry_link.go.tmpl diff --git a/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml b/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml index 4ee1f332f72a..83546b427bee 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml @@ -35,6 +35,7 @@ async: operation: base_url: '{{op_id}}' autogen_async: true +flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl constants: templates/terraform/constants/iam_workforce_pool_provider.go.tmpl diff --git a/mmv1/products/kms/SecretCiphertext.yaml b/mmv1/products/kms/SecretCiphertext.yaml index f85549ea38b2..e62e6ed0b552 100644 --- a/mmv1/products/kms/SecretCiphertext.yaml +++ b/mmv1/products/kms/SecretCiphertext.yaml @@ -35,6 +35,7 @@ exclude_import: true exclude_delete: true supports_indirect_user_project_override: true exclude_tgc: true +flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/noop.go.tmpl post_create: templates/terraform/post_create/kms_secret_ciphertext.go.tmpl diff --git a/mmv1/products/osconfig/PatchDeployment.yaml b/mmv1/products/osconfig/PatchDeployment.yaml index 91631d42ba1b..b347ef3caf82 100644 --- a/mmv1/products/osconfig/PatchDeployment.yaml +++ b/mmv1/products/osconfig/PatchDeployment.yaml @@ -27,6 +27,7 @@ create_url: projects/{{project}}/patchDeployments?patchDeploymentId={{patch_depl import_format: - '{{project}} {{name}}' - '{{name}}' +flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/os_config_patch_deployment.go.tmpl decoder: templates/terraform/decoders/os_config_patch_deployment.go.tmpl From eb745508e05196ac2e077782b231ed875035ac8f Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 17:08:24 -0700 Subject: [PATCH 025/100] flatten{{resourceName}}Resource signature in resource.go.tmpl --- mmv1/products/kms/CryptoKey.yaml | 1 + mmv1/products/kms/KeyRing.yaml | 1 + mmv1/products/spanner/Instance.yaml | 2 ++ mmv1/products/spanner/InstanceConfig.yaml | 1 + 4 files changed, 5 insertions(+) diff --git a/mmv1/products/kms/CryptoKey.yaml b/mmv1/products/kms/CryptoKey.yaml index 2df23c9526ad..aa802a6a0144 100644 --- a/mmv1/products/kms/CryptoKey.yaml +++ b/mmv1/products/kms/CryptoKey.yaml @@ -52,6 +52,7 @@ custom_code: schema_version: 1 state_upgraders: true supports_indirect_user_project_override: true +flatten_all_in_method: true examples: - name: 'kms_crypto_key_basic' primary_resource_id: 'example-key' diff --git a/mmv1/products/kms/KeyRing.yaml b/mmv1/products/kms/KeyRing.yaml index 6cca3351f8a0..2165f2448cb0 100644 --- a/mmv1/products/kms/KeyRing.yaml +++ b/mmv1/products/kms/KeyRing.yaml @@ -38,6 +38,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +flatten_all_in_method: true custom_code: tgc_ignore_terraform_decoder: true encoder: 'templates/terraform/encoders/send_nil_body.go.tmpl' diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 95053fa49e9f..828cc7a1a83f 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -30,6 +30,8 @@ import_format: - '{{name}}' cai_asset_name_format: 'projects/{{project}}/instances/{{name}}' include_in_tgc_next: true + +flatten_all_in_method: true timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/products/spanner/InstanceConfig.yaml b/mmv1/products/spanner/InstanceConfig.yaml index d1c00291d72f..7241e4913320 100644 --- a/mmv1/products/spanner/InstanceConfig.yaml +++ b/mmv1/products/spanner/InstanceConfig.yaml @@ -34,6 +34,7 @@ timeouts: update_minutes: 20 delete_minutes: 20 autogen_async: true +flatten_all_in_method: true async: actions: ['create', 'update'] type: 'OpAsync' From ed75e3af682a47bfa0c778c6ab030123941acc6a Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 7 Apr 2026 22:35:29 -0700 Subject: [PATCH 026/100] default run of flattenAllInResource --- mmv1/api/resource.go | 3 --- .../ServicePerimeterDryRunEgressPolicy.yaml | 1 - .../ServicePerimeterDryRunIngressPolicy.yaml | 1 - .../ServicePerimeterDryRunResource.yaml | 1 - .../ServicePerimeterEgressPolicy.yaml | 1 - .../ServicePerimeterIngressPolicy.yaml | 1 - .../ServicePerimeterResource.yaml | 1 - mmv1/products/activedirectory/DomainTrust.yaml | 1 - mmv1/products/apigee/DeveloperApp.yaml | 1 - .../products/apigee/EnvironmentAddonsConfig.yaml | 1 - .../products/apigee/EnvironmentKeyvaluemaps.yaml | 1 - mmv1/products/apigee/NatAddress.yaml | 1 - mmv1/products/appengine/DomainMapping.yaml | 1 - .../DataExchangeSubscription.yaml | 1 - .../ListingSubscription.yaml | 1 - mmv1/products/bigquerydatatransfer/Config.yaml | 1 - mmv1/products/chronicle/DashboardChart.yaml | 1 - mmv1/products/cloudbilling/ProjectInfo.yaml | 1 - mmv1/products/cloudrun/DomainMapping.yaml | 1 - mmv1/products/cloudrun/Service.yaml | 1 - mmv1/products/compute/BackendService.yaml | 1 - mmv1/products/compute/Disk.yaml | 1 - .../compute/DiskResourcePolicyAttachment.yaml | 1 - .../compute/FirewallPolicyWithRules.yaml | 1 - mmv1/products/compute/GlobalNetworkEndpoint.yaml | 1 - mmv1/products/compute/Network.yaml | 1 - mmv1/products/compute/NetworkEndpoint.yaml | 1 - mmv1/products/compute/NetworkEndpoints.yaml | 1 - .../compute/NetworkFirewallPolicyWithRules.yaml | 1 - mmv1/products/compute/RegionBackendService.yaml | 1 - mmv1/products/compute/RegionDisk.yaml | 1 - .../RegionDiskResourcePolicyAttachment.yaml | 1 - mmv1/products/compute/RegionNetworkEndpoint.yaml | 1 - .../RegionNetworkFirewallPolicyWithRules.yaml | 1 - .../products/compute/RegionTargetHttpsProxy.yaml | 1 - .../compute/ResourcePolicyAttachment.yaml | 1 - mmv1/products/compute/Route.yaml | 1 - mmv1/products/compute/RouterRoutePolicy.yaml | 1 - mmv1/products/compute/Snapshot.yaml | 1 - mmv1/products/containeranalysis/Note.yaml | 1 - mmv1/products/containeranalysis/Occurrence.yaml | 1 - mmv1/products/dataplex/Entry.yaml | 1 - mmv1/products/dataplex/EntryLink.yaml | 1 - mmv1/products/dataproc/Batch.yaml | 1 - mmv1/products/dlp/DeidentifyTemplate.yaml | 1 - mmv1/products/dlp/DiscoveryConfig.yaml | 1 - mmv1/products/dlp/InspectTemplate.yaml | 1 - mmv1/products/dlp/JobTrigger.yaml | 1 - mmv1/products/dlp/StoredInfoType.yaml | 1 - mmv1/products/firebasedatabase/Instance.yaml | 1 - mmv1/products/firestore/Document.yaml | 1 - mmv1/products/healthcare/Dataset.yaml | 1 - mmv1/products/healthcare/DicomStore.yaml | 1 - mmv1/products/healthcare/FhirStore.yaml | 1 - mmv1/products/healthcare/Hl7V2Store.yaml | 1 - mmv1/products/healthcare/PipelineJob.yaml | 1 - mmv1/products/iambeta/WorkloadIdentityPool.yaml | 10 +--------- .../WorkloadIdentityPoolManagedIdentity.yaml | 1 - .../iambeta/WorkloadIdentityPoolNamespace.yaml | 1 - .../iambeta/WorkloadIdentityPoolProvider.yaml | 1 - mmv1/products/iamworkforcepool/OauthClient.yaml | 1 - .../iamworkforcepool/OauthClientCredential.yaml | 1 - .../products/iamworkforcepool/WorkforcePool.yaml | 1 - .../iamworkforcepool/WorkforcePoolProvider.yaml | 1 - .../WorkforcePoolProviderScimTenant.yaml | 1 - .../WorkforcePoolProviderScimToken.yaml | 1 - mmv1/products/integrations/Client.yaml | 1 - mmv1/products/kms/CryptoKey.yaml | 1 - mmv1/products/kms/KeyHandle.yaml | 1 - mmv1/products/kms/KeyRing.yaml | 1 - mmv1/products/kms/SecretCiphertext.yaml | 1 - mmv1/products/memorystore/Instance.yaml | 1 - mmv1/products/monitoring/MonitoredProject.yaml | 1 - .../products/monitoring/NotificationChannel.yaml | 1 - mmv1/products/osconfig/PatchDeployment.yaml | 1 - mmv1/products/privateca/CaPool.yaml | 1 - .../products/privateca/CertificateAuthority.yaml | 1 - mmv1/products/redis/Cluster.yaml | 1 - mmv1/products/redis/Instance.yaml | 1 - mmv1/products/resourcemanager/Lien.yaml | 1 - mmv1/products/secretmanager/Secret.yaml | 1 - mmv1/products/secretmanager/SecretVersion.yaml | 1 - .../RegionalSecretVersion.yaml | 1 - mmv1/products/servicedirectory/Endpoint.yaml | 1 - mmv1/products/spanner/BackupSchedule.yaml | 1 - mmv1/products/spanner/Database.yaml | 1 - mmv1/products/spanner/Instance.yaml | 1 - mmv1/products/spanner/InstanceConfig.yaml | 1 - mmv1/products/sql/Database.yaml | 1 - .../sql/SourceRepresentationInstance.yaml | 16 +++++++++++++++- mmv1/products/storage/HmacKey.yaml | 1 - .../vertexai/IndexEndpointDeployedIndex.yaml | 1 - mmv1/products/vmwareengine/PrivateCloud.yaml | 1 - mmv1/products/vpcaccess/Connector.yaml | 1 - 94 files changed, 16 insertions(+), 104 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 3f29b38b38e8..bffb7033da2b 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -368,9 +368,6 @@ type Resource struct { CustomCode resource.CustomCode `yaml:"custom_code,omitempty"` - // If true it will generate all flatteners in a flatten{{resourceName}} method instead of generating all flatteners in Read() - FlattenAllInMethod bool `yaml:"flatten_all_in_method,omitempty"` - // Examples in documentation. Backed by generated tests, and have // corresponding OiCS walkthroughs. Examples []*resource.Examples `yaml:"examples,omitempty"` diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml index 7883b192b5be..606f6021a50d 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml @@ -69,7 +69,6 @@ nested_query: - egressPolicies is_list_of_ids: false modify_by_patch: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_dry_run_egress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml index 7bbfbfbca059..4675d4196ef4 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml @@ -70,7 +70,6 @@ nested_query: - ingressPolicies is_list_of_ids: false modify_by_patch: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_dry_run_egress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml index 31619351f6ef..54f3fb892503 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml @@ -66,7 +66,6 @@ nested_query: - resources is_list_of_ids: true modify_by_patch: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_dry_run_resource.go.tmpl' pre_create: 'templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index a34be5c21280..d68a16a4515d 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -69,7 +69,6 @@ nested_query: - egressPolicies is_list_of_ids: false modify_by_patch: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' custom_import: 'templates/terraform/custom_import/access_context_manager_service_perimeter_egress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index da6f095daed0..8eaff084e78d 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -70,7 +70,6 @@ nested_query: - ingressPolicies is_list_of_ids: false modify_by_patch: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/access_context_manager.go.tmpl' custom_import: 'templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.tmpl' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml index e9c5adcf9a2a..cecf0c7af172 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml @@ -66,7 +66,6 @@ nested_query: - resources is_list_of_ids: true modify_by_patch: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/access_context_manager_service_perimeter_resource.go.tmpl' custom_import: 'templates/terraform/custom_import/access_context_manager_service_perimeter_resource.go.tmpl' diff --git a/mmv1/products/activedirectory/DomainTrust.yaml b/mmv1/products/activedirectory/DomainTrust.yaml index ed54fcf8c984..93771ad0c432 100644 --- a/mmv1/products/activedirectory/DomainTrust.yaml +++ b/mmv1/products/activedirectory/DomainTrust.yaml @@ -51,7 +51,6 @@ nested_query: - trusts is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/active_directory_domain_trust.go.tmpl' update_encoder: 'templates/terraform/update_encoder/active_directory_domain_trust.go.tmpl' diff --git a/mmv1/products/apigee/DeveloperApp.yaml b/mmv1/products/apigee/DeveloperApp.yaml index 55b07513f3bb..de66238ac526 100644 --- a/mmv1/products/apigee/DeveloperApp.yaml +++ b/mmv1/products/apigee/DeveloperApp.yaml @@ -29,7 +29,6 @@ update_mask: false update_verb: "PUT" import_format: - "{{org_id}}/developers/{{developer_email}}/apps/{{name}}" -flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/apigee_developer_app.go.tmpl" custom_import: "templates/terraform/custom_import/apigee_developer_app.go.tmpl" diff --git a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml index e640c4947492..972482ae7432 100644 --- a/mmv1/products/apigee/EnvironmentAddonsConfig.yaml +++ b/mmv1/products/apigee/EnvironmentAddonsConfig.yaml @@ -37,7 +37,6 @@ async: import_format: - '{{env_id}}' id_format: '{{env_id}}' -flatten_all_in_method: true custom_code: custom_import: 'templates/terraform/custom_import/apigee_env_addons.go.tmpl' decoder: 'templates/terraform/decoders/apigee_env_addons.go.tmpl' diff --git a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml index bdc8a878ec5b..938d328a6a92 100644 --- a/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml +++ b/mmv1/products/apigee/EnvironmentKeyvaluemaps.yaml @@ -34,7 +34,6 @@ timeouts: update_minutes: 20 delete_minutes: 1 autogen_async: true -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/apigee_environment_keyvaluemaps.go.tmpl' custom_create: 'templates/terraform/custom_create/apigee_environment_keyvaluemaps.go.tmpl' diff --git a/mmv1/products/apigee/NatAddress.yaml b/mmv1/products/apigee/NatAddress.yaml index 3ab99203e109..916e33d2be46 100644 --- a/mmv1/products/apigee/NatAddress.yaml +++ b/mmv1/products/apigee/NatAddress.yaml @@ -40,7 +40,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/apigee_nat_address.go.tmpl' encoder: 'templates/terraform/encoders/apigee_nat_address.go.tmpl' diff --git a/mmv1/products/appengine/DomainMapping.yaml b/mmv1/products/appengine/DomainMapping.yaml index 42234352b931..1e9995803021 100644 --- a/mmv1/products/appengine/DomainMapping.yaml +++ b/mmv1/products/appengine/DomainMapping.yaml @@ -39,7 +39,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/app_engine_domain_mapping.go.tmpl' examples: diff --git a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml index 69a1c860d173..bc965f172b43 100644 --- a/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/DataExchangeSubscription.yaml @@ -29,7 +29,6 @@ self_link: 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscrip create_url: 'projects/{{data_exchange_project}}/locations/{{data_exchange_location}}/dataExchanges/{{data_exchange_id}}:subscribe' import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' encoder: 'templates/terraform/encoders/bigqueryanalyticshub_data_exchange_subscription.go.tmpl' diff --git a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml index 48b6ae02f804..e9b68a3ee1c9 100644 --- a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml @@ -29,7 +29,6 @@ create_url: 'projects/{{project}}/locations/{{location}}/dataExchanges/{{data_ex immutable: true import_format: - 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}' -flatten_all_in_method: true custom_code: constants: templates/terraform/constants/bigqueryanalyticshub_listing_subscription.go.tmpl decoder: 'templates/terraform/decoders/bigqueryanalyticshub_listing_subscription.go.tmpl' diff --git a/mmv1/products/bigquerydatatransfer/Config.yaml b/mmv1/products/bigquerydatatransfer/Config.yaml index c8b0608a32ec..b7aef36e1dbb 100644 --- a/mmv1/products/bigquerydatatransfer/Config.yaml +++ b/mmv1/products/bigquerydatatransfer/Config.yaml @@ -34,7 +34,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/bigquery_data_transfer.go.tmpl' encoder: 'templates/terraform/encoders/bigquery_data_transfer.go.tmpl' diff --git a/mmv1/products/chronicle/DashboardChart.yaml b/mmv1/products/chronicle/DashboardChart.yaml index 76b4039b6859..d9bf0c3f81ba 100644 --- a/mmv1/products/chronicle/DashboardChart.yaml +++ b/mmv1/products/chronicle/DashboardChart.yaml @@ -34,7 +34,6 @@ delete_verb: POST import_format: - projects/{{project}}/locations/{{location}}/instances/{{instance}}/dashboardCharts/{{chart_id}} -flatten_all_in_method: true custom_code: pre_delete: "templates/terraform/pre_delete/chronicle_dashboard_chart.go.tmpl" pre_update: "templates/terraform/pre_update/chronicle_dashboard_chart_dashboard_query.go.tmpl" diff --git a/mmv1/products/cloudbilling/ProjectInfo.yaml b/mmv1/products/cloudbilling/ProjectInfo.yaml index a85f317cffa0..b692332973cb 100644 --- a/mmv1/products/cloudbilling/ProjectInfo.yaml +++ b/mmv1/products/cloudbilling/ProjectInfo.yaml @@ -28,7 +28,6 @@ import_format: - projects/{{%project}} - '{{%project}}' cai_asset_name_format: projects/{{project}}/billingInfo -flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/billing_project_info.go.tmpl decoder: templates/terraform/decoders/billing_project_info.go.tmpl diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 383845d24852..9c3aa87e6ac8 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -40,7 +40,6 @@ error_retry_predicates: schema_version: 1 state_upgraders: true cai_asset_name_format: projects/{{project}}/locations/{{location}}/domainmappings/{{name}} -flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/cloud_run_domain_mapping.go.tmpl decoder: templates/terraform/decoders/cloud_run.go.tmpl diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index fe5e906f21f8..6f8fe3a5cadc 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -51,7 +51,6 @@ iam_policy: import_format: - 'projects/{{project}}/locations/{{location}}/services/{{service}}' - '{{service}}' -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/cloud_run_service.go.tmpl' encoder: 'templates/terraform/encoders/cloud_run_service.go.tmpl' diff --git a/mmv1/products/compute/BackendService.yaml b/mmv1/products/compute/BackendService.yaml index 058ed39167ee..917edfab2323 100644 --- a/mmv1/products/compute/BackendService.yaml +++ b/mmv1/products/compute/BackendService.yaml @@ -52,7 +52,6 @@ include_in_tgc_next: true tgc_tests: - name: 'TestAccComputeBackendService_backendServiceCustomMetrics_update' skip: 'Test framework problem with single vs multiple block parsing of custom_metrics' -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/backend_service.go.tmpl' encoder: 'templates/terraform/encoders/backend_service.go.tmpl' diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index f3b5fe09233e..745344fd2f6f 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -57,7 +57,6 @@ iam_policy: - 'projects/{{project}}/zones/{{zone}}/disks/{{name}}' - '{{name}}' include_in_tgc_next: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/disk.tmpl' encoder: 'templates/terraform/encoders/disk.tmpl' diff --git a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml index f5dba0b2553d..eba8c82256b6 100644 --- a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml @@ -45,7 +45,6 @@ nested_query: - resourcePolicies is_list_of_ids: true modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_disk_resource_policies_attachment.go.tmpl' decoder: 'templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl' diff --git a/mmv1/products/compute/FirewallPolicyWithRules.yaml b/mmv1/products/compute/FirewallPolicyWithRules.yaml index 96a50146221c..736a927304dc 100644 --- a/mmv1/products/compute/FirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/FirewallPolicyWithRules.yaml @@ -29,7 +29,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/GlobalNetworkEndpoint.yaml b/mmv1/products/compute/GlobalNetworkEndpoint.yaml index 06a6a3a02faf..740696cb9e60 100644 --- a/mmv1/products/compute/GlobalNetworkEndpoint.yaml +++ b/mmv1/products/compute/GlobalNetworkEndpoint.yaml @@ -53,7 +53,6 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_global_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/Network.yaml b/mmv1/products/compute/Network.yaml index 465e8df8812c..3eb25579fa14 100644 --- a/mmv1/products/compute/Network.yaml +++ b/mmv1/products/compute/Network.yaml @@ -42,7 +42,6 @@ sweeper: # - "google_network_security_intercept_deployment_group" (beta only) - "google_network_security_firewall_endpoint_association" include_in_tgc_next: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_network.go.tmpl' update_encoder: 'templates/terraform/update_encoder/compute_network.go.tmpl' diff --git a/mmv1/products/compute/NetworkEndpoint.yaml b/mmv1/products/compute/NetworkEndpoint.yaml index 11b29e0126fc..67b16dc943d7 100644 --- a/mmv1/products/compute/NetworkEndpoint.yaml +++ b/mmv1/products/compute/NetworkEndpoint.yaml @@ -59,7 +59,6 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/unwrap_resource.go.tmpl' diff --git a/mmv1/products/compute/NetworkEndpoints.yaml b/mmv1/products/compute/NetworkEndpoints.yaml index 37edf62b0647..4bc74355c5b1 100644 --- a/mmv1/products/compute/NetworkEndpoints.yaml +++ b/mmv1/products/compute/NetworkEndpoints.yaml @@ -58,7 +58,6 @@ async: resource_inside_response: false identity: - networkEndpointGroup -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/network_endpoints.go.tmpl' encoder: 'templates/terraform/encoders/compute_network_endpoints.go.tmpl' diff --git a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml index a7b86a90683d..f82f8c7981af 100644 --- a/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/NetworkFirewallPolicyWithRules.yaml @@ -31,7 +31,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index 174c65387673..057fa35c3194 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -47,7 +47,6 @@ iam_policy: iam_conditions_request_type: 'QUERY_PARAM' min_version: 'beta' include_in_tgc_next: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/region_backend_service.go.tmpl' encoder: 'templates/terraform/encoders/region_backend_service.go.tmpl' diff --git a/mmv1/products/compute/RegionDisk.yaml b/mmv1/products/compute/RegionDisk.yaml index 24b0cef69fc7..c34dd4dd4ed5 100644 --- a/mmv1/products/compute/RegionDisk.yaml +++ b/mmv1/products/compute/RegionDisk.yaml @@ -59,7 +59,6 @@ iam_policy: - 'projects/{{project}}/regions/{{region}}/disks/{{name}}' - '{{name}}' include_in_tgc_next: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/region_disk.go.tmpl' encoder: 'templates/terraform/encoders/disk.tmpl' diff --git a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml index 8778b2734084..aa47a8ff28ab 100644 --- a/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/RegionDiskResourcePolicyAttachment.yaml @@ -36,7 +36,6 @@ id_format: '{{project}}/{{region}}/{{disk}}/{{name}}' async: operation: base_url: '{{op_id}}' -flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/compute_region_disk_resource_policies_attachment.go.tmpl decoder: templates/terraform/decoders/compute_disk_resource_policies_attachment.go.tmpl diff --git a/mmv1/products/compute/RegionNetworkEndpoint.yaml b/mmv1/products/compute/RegionNetworkEndpoint.yaml index 37da1a094851..979a9d3126e7 100644 --- a/mmv1/products/compute/RegionNetworkEndpoint.yaml +++ b/mmv1/products/compute/RegionNetworkEndpoint.yaml @@ -55,7 +55,6 @@ nested_query: - items is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_region_network_endpoint.go.tmpl' decoder: 'templates/terraform/decoders/network_endpoint.go.tmpl' diff --git a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml index 36777743df96..3690677e0024 100644 --- a/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml +++ b/mmv1/products/compute/RegionNetworkFirewallPolicyWithRules.yaml @@ -31,7 +31,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' encoder: 'templates/terraform/encoders/resource_compute_region_network_firewall_policy_with_rules.go.tmpl' diff --git a/mmv1/products/compute/RegionTargetHttpsProxy.yaml b/mmv1/products/compute/RegionTargetHttpsProxy.yaml index 9f4da8c9e3ca..556287dcac6b 100644 --- a/mmv1/products/compute/RegionTargetHttpsProxy.yaml +++ b/mmv1/products/compute/RegionTargetHttpsProxy.yaml @@ -37,7 +37,6 @@ async: result: resource_inside_response: false include_in_tgc_next: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/compute_region_target_https_proxy.go.tmpl' # update_encoder is usually the same as encoder by default. This resource is an uncommon case where the whole resource diff --git a/mmv1/products/compute/ResourcePolicyAttachment.yaml b/mmv1/products/compute/ResourcePolicyAttachment.yaml index 2ae9f3b7ddf5..9d41f9a760c4 100644 --- a/mmv1/products/compute/ResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/ResourcePolicyAttachment.yaml @@ -38,7 +38,6 @@ id_format: '{{project}}/{{zone}}/{{instance}}/{{name}}' async: operation: base_url: '{{op_id}}' -flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/compute_resource_policy_attachment.go.tmpl decoder: templates/terraform/decoders/compute_resource_policy_attachment.go.tmpl diff --git a/mmv1/products/compute/Route.yaml b/mmv1/products/compute/Route.yaml index 010cda564696..2ca914168299 100644 --- a/mmv1/products/compute/Route.yaml +++ b/mmv1/products/compute/Route.yaml @@ -65,7 +65,6 @@ async: resource_inside_response: false collection_url_key: 'items' include_in_tgc_next: true -flatten_all_in_method: true custom_code: extra_schema_entry: 'templates/terraform/extra_schema_entry/route.tmpl' constants: 'templates/terraform/constants/compute_route.go.tmpl' diff --git a/mmv1/products/compute/RouterRoutePolicy.yaml b/mmv1/products/compute/RouterRoutePolicy.yaml index adf91fc1726f..0d4dd3bc8069 100644 --- a/mmv1/products/compute/RouterRoutePolicy.yaml +++ b/mmv1/products/compute/RouterRoutePolicy.yaml @@ -42,7 +42,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/unwrap_route_policy_resource.go.tmpl' examples: diff --git a/mmv1/products/compute/Snapshot.yaml b/mmv1/products/compute/Snapshot.yaml index 81dee719ea9d..7ebc4b6f4280 100644 --- a/mmv1/products/compute/Snapshot.yaml +++ b/mmv1/products/compute/Snapshot.yaml @@ -55,7 +55,6 @@ iam_policy: - 'projects/{{project}}/global/snapshots/{{name}}' - '{{name}}' include_in_tgc_next: true -flatten_all_in_method: true custom_code: tgc_decoder: 'templates/tgc_next/decoders/compute_snapshot.go.tmpl' decoder: 'templates/terraform/decoders/snapshot.go.tmpl' diff --git a/mmv1/products/containeranalysis/Note.yaml b/mmv1/products/containeranalysis/Note.yaml index a92a2cf9e8a9..5effb9e85704 100644 --- a/mmv1/products/containeranalysis/Note.yaml +++ b/mmv1/products/containeranalysis/Note.yaml @@ -42,7 +42,6 @@ iam_policy: import_format: - 'projects/{{project}}/notes/{{name}}' - '{{name}}' -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/containeranalysis_attestation_field_name.go.tmpl' decoder: 'templates/terraform/decoders/containeranalysis_attestation_field_name.go.tmpl' diff --git a/mmv1/products/containeranalysis/Occurrence.yaml b/mmv1/products/containeranalysis/Occurrence.yaml index 4a94beead5fd..78f4e19ecfce 100644 --- a/mmv1/products/containeranalysis/Occurrence.yaml +++ b/mmv1/products/containeranalysis/Occurrence.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/containeranalysis_occurrence.go.tmpl' update_encoder: 'templates/terraform/update_encoder/containeranalysis_occurrence.go.tmpl' diff --git a/mmv1/products/dataplex/Entry.yaml b/mmv1/products/dataplex/Entry.yaml index 1e720b34d5a2..a9ba0c7ac46a 100644 --- a/mmv1/products/dataplex/Entry.yaml +++ b/mmv1/products/dataplex/Entry.yaml @@ -39,7 +39,6 @@ update_mask: true import_format: - 'projects/{{project}}/locations/{{location}}/entryGroups/{{entry_group_id}}/entries/{{entry_id}}' -flatten_all_in_method: true custom_code: constants: templates/terraform/constants/dataplex_entry.go.tmpl decoder: templates/terraform/decoders/dataplex_entry.go.tmpl diff --git a/mmv1/products/dataplex/EntryLink.yaml b/mmv1/products/dataplex/EntryLink.yaml index 1943975ef43e..5a5689464590 100644 --- a/mmv1/products/dataplex/EntryLink.yaml +++ b/mmv1/products/dataplex/EntryLink.yaml @@ -26,7 +26,6 @@ create_url: 'projects/{{project}}/locations/{{location}}/entryGroups/{{entry_gro update_verb: 'PATCH' import_format: - 'projects/{{project}}/locations/{{location}}/entryGroups/{{entry_group_id}}/entryLinks/{{entry_link_id}}' -flatten_all_in_method: true custom_code: constants: templates/terraform/constants/dataplex_entry_link.go.tmpl decoder: templates/terraform/decoders/dataplex_entry_link.go.tmpl diff --git a/mmv1/products/dataproc/Batch.yaml b/mmv1/products/dataproc/Batch.yaml index 2d641151ea63..d0f07545700b 100644 --- a/mmv1/products/dataproc/Batch.yaml +++ b/mmv1/products/dataproc/Batch.yaml @@ -39,7 +39,6 @@ async: base_url: '{{op_id}}' autogen_async: true include_in_tgc_next: true -flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/cloud_dataproc_batch.go.tmpl constants: templates/terraform/constants/cloud_dataproc_batch.go.tmpl diff --git a/mmv1/products/dlp/DeidentifyTemplate.yaml b/mmv1/products/dlp/DeidentifyTemplate.yaml index b4396a566980..8ff5250fb9d6 100644 --- a/mmv1/products/dlp/DeidentifyTemplate.yaml +++ b/mmv1/products/dlp/DeidentifyTemplate.yaml @@ -30,7 +30,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/wrap_object_with_template_id.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/DiscoveryConfig.yaml b/mmv1/products/dlp/DiscoveryConfig.yaml index 6db8dec372d5..4c27e6d0ce49 100644 --- a/mmv1/products/dlp/DiscoveryConfig.yaml +++ b/mmv1/products/dlp/DiscoveryConfig.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/InspectTemplate.yaml b/mmv1/products/dlp/InspectTemplate.yaml index 1768debd78c7..5ea7f2adb359 100644 --- a/mmv1/products/dlp/InspectTemplate.yaml +++ b/mmv1/products/dlp/InspectTemplate.yaml @@ -30,7 +30,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/wrap_object_with_template_id.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/JobTrigger.yaml b/mmv1/products/dlp/JobTrigger.yaml index 3a0b809b1cea..873b07e2fd8d 100644 --- a/mmv1/products/dlp/JobTrigger.yaml +++ b/mmv1/products/dlp/JobTrigger.yaml @@ -30,7 +30,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/dlp_job_trigger.go.tmpl' update_encoder: 'templates/terraform/encoders/wrap_object.go.tmpl' diff --git a/mmv1/products/dlp/StoredInfoType.yaml b/mmv1/products/dlp/StoredInfoType.yaml index af6492d0b642..acb2700e2bce 100644 --- a/mmv1/products/dlp/StoredInfoType.yaml +++ b/mmv1/products/dlp/StoredInfoType.yaml @@ -37,7 +37,6 @@ async: suppress_error: false target_occurrences: 1 actions: ['create'] -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/dlp_stored_info_type.go.tmpl' encoder: 'templates/terraform/encoders/dlp_stored_info_type.go.tmpl' diff --git a/mmv1/products/firebasedatabase/Instance.yaml b/mmv1/products/firebasedatabase/Instance.yaml index 4bf27c916d25..469473b18e8a 100644 --- a/mmv1/products/firebasedatabase/Instance.yaml +++ b/mmv1/products/firebasedatabase/Instance.yaml @@ -31,7 +31,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/firebase_database_instance.go.tmpl' decoder: 'templates/terraform/decoders/firebase_database_instance.go.tmpl' diff --git a/mmv1/products/firestore/Document.yaml b/mmv1/products/firestore/Document.yaml index f15b6c8fd91d..604724f3d6ed 100644 --- a/mmv1/products/firestore/Document.yaml +++ b/mmv1/products/firestore/Document.yaml @@ -40,7 +40,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/firestore_document.go.tmpl' custom_import: 'templates/terraform/custom_import/firestore_document.go.tmpl' diff --git a/mmv1/products/healthcare/Dataset.yaml b/mmv1/products/healthcare/Dataset.yaml index 6e53ef81e584..d8313d98ba65 100644 --- a/mmv1/products/healthcare/Dataset.yaml +++ b/mmv1/products/healthcare/Dataset.yaml @@ -32,7 +32,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' error_retry_predicates: diff --git a/mmv1/products/healthcare/DicomStore.yaml b/mmv1/products/healthcare/DicomStore.yaml index 8409bf02ae5e..2e2c9b448e33 100644 --- a/mmv1/products/healthcare/DicomStore.yaml +++ b/mmv1/products/healthcare/DicomStore.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_dicom_store.go.tmpl' diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index 660786dd4786..e8d5fcdcd9b2 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_fhir_store.go.tmpl' diff --git a/mmv1/products/healthcare/Hl7V2Store.yaml b/mmv1/products/healthcare/Hl7V2Store.yaml index b5a076b7a476..c2bea16e4880 100644 --- a/mmv1/products/healthcare/Hl7V2Store.yaml +++ b/mmv1/products/healthcare/Hl7V2Store.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' custom_import: 'templates/terraform/custom_import/healthcare_hl7_v2_store.go.tmpl' diff --git a/mmv1/products/healthcare/PipelineJob.yaml b/mmv1/products/healthcare/PipelineJob.yaml index b2fae67c1dda..260f4380a098 100644 --- a/mmv1/products/healthcare/PipelineJob.yaml +++ b/mmv1/products/healthcare/PipelineJob.yaml @@ -71,7 +71,6 @@ examples: source_fhirstore_name: 'source_fhir_store' dest_fhirstore_name: 'dest_fhir_store' bucket_name: 'example_bucket_name' -flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/long_name_to_self_link.go.tmpl parameters: diff --git a/mmv1/products/iambeta/WorkloadIdentityPool.yaml b/mmv1/products/iambeta/WorkloadIdentityPool.yaml index 3da493bab266..78bd8e249393 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPool.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPool.yaml @@ -52,6 +52,7 @@ iam_policy: - '{{workload_identity_pool_id}}' allowed_iam_role: 'roles/iam.workloadIdentityPoolViewer' iam_conditions_request_type: 'REQUEST_BODY' + min_version: beta custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' @@ -277,15 +278,6 @@ properties: PEM certificate of the PKI used for validation. Must only contain one ca certificate(either root or intermediate cert). required: true - - name: 'trustDefaultSharedCa' - type: Boolean - description: | - If set to True, the trust bundle will include the private ca managed identity regional root - public certificates. - - - ~> **Note** `trust_default_shared_ca` is only supported for managed identity trust domain - resource. - name: 'attestationRules' is_missing_in_cai: true type: Array diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml index e4a0c240b7d9..a737e20e0673 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolManagedIdentity.yaml @@ -28,7 +28,6 @@ update_mask: true import_format: - 'projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/namespaces/{{workload_identity_pool_namespace_id}}/managedIdentities/{{workload_identity_pool_managed_identity_id}}' autogen_async: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool_managed_identity.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml index c5349e15230b..71ec2fc53efb 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolNamespace.yaml @@ -29,7 +29,6 @@ update_mask: true import_format: - 'projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/namespaces/{{workload_identity_pool_namespace_id}}' autogen_async: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool_namespace.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml index 27fef881088e..caf7a27ba67b 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml @@ -39,7 +39,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool_provider.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iamworkforcepool/OauthClient.yaml b/mmv1/products/iamworkforcepool/OauthClient.yaml index a57d0629cfd9..8fd0b6edc4d9 100644 --- a/mmv1/products/iamworkforcepool/OauthClient.yaml +++ b/mmv1/products/iamworkforcepool/OauthClient.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl" test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client.go.tmpl" diff --git a/mmv1/products/iamworkforcepool/OauthClientCredential.yaml b/mmv1/products/iamworkforcepool/OauthClientCredential.yaml index 0eab9a7c47e8..bacf221fadcd 100644 --- a/mmv1/products/iamworkforcepool/OauthClientCredential.yaml +++ b/mmv1/products/iamworkforcepool/OauthClientCredential.yaml @@ -33,7 +33,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl" test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client_credential.go.tmpl" diff --git a/mmv1/products/iamworkforcepool/WorkforcePool.yaml b/mmv1/products/iamworkforcepool/WorkforcePool.yaml index 150078065a91..eb874320e32d 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePool.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePool.yaml @@ -43,7 +43,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/iam_workforce_pool.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml b/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml index 83546b427bee..4ee1f332f72a 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePoolProvider.yaml @@ -35,7 +35,6 @@ async: operation: base_url: '{{op_id}}' autogen_async: true -flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl constants: templates/terraform/constants/iam_workforce_pool_provider.go.tmpl diff --git a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml index a8f53653b190..2370e40ebee1 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimTenant.yaml @@ -31,7 +31,6 @@ update_mask: true timeouts: insert_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' post_create: 'templates/terraform/post_create/sleep.go.tmpl' diff --git a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml index b9c27ecc48e7..1023d021c4c6 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePoolProviderScimToken.yaml @@ -31,7 +31,6 @@ update_mask: true timeouts: insert_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' post_create: 'templates/terraform/post_create/sleep.go.tmpl' diff --git a/mmv1/products/integrations/Client.yaml b/mmv1/products/integrations/Client.yaml index 01b336556db9..a3ddc281162e 100644 --- a/mmv1/products/integrations/Client.yaml +++ b/mmv1/products/integrations/Client.yaml @@ -34,7 +34,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/integrations_client.go.tmpl' pre_create: 'templates/terraform/pre_create/integrations_client.go.tmpl' diff --git a/mmv1/products/kms/CryptoKey.yaml b/mmv1/products/kms/CryptoKey.yaml index aa802a6a0144..2df23c9526ad 100644 --- a/mmv1/products/kms/CryptoKey.yaml +++ b/mmv1/products/kms/CryptoKey.yaml @@ -52,7 +52,6 @@ custom_code: schema_version: 1 state_upgraders: true supports_indirect_user_project_override: true -flatten_all_in_method: true examples: - name: 'kms_crypto_key_basic' primary_resource_id: 'example-key' diff --git a/mmv1/products/kms/KeyHandle.yaml b/mmv1/products/kms/KeyHandle.yaml index 75ba2a99faf6..6c4fe2505432 100644 --- a/mmv1/products/kms/KeyHandle.yaml +++ b/mmv1/products/kms/KeyHandle.yaml @@ -46,7 +46,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/kms.go.tmpl' tgc_decoder: 'templates/tgc_next/decoders/kms.go.tmpl' diff --git a/mmv1/products/kms/KeyRing.yaml b/mmv1/products/kms/KeyRing.yaml index 2165f2448cb0..6cca3351f8a0 100644 --- a/mmv1/products/kms/KeyRing.yaml +++ b/mmv1/products/kms/KeyRing.yaml @@ -38,7 +38,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: tgc_ignore_terraform_decoder: true encoder: 'templates/terraform/encoders/send_nil_body.go.tmpl' diff --git a/mmv1/products/kms/SecretCiphertext.yaml b/mmv1/products/kms/SecretCiphertext.yaml index e62e6ed0b552..f85549ea38b2 100644 --- a/mmv1/products/kms/SecretCiphertext.yaml +++ b/mmv1/products/kms/SecretCiphertext.yaml @@ -35,7 +35,6 @@ exclude_import: true exclude_delete: true supports_indirect_user_project_override: true exclude_tgc: true -flatten_all_in_method: true custom_code: decoder: templates/terraform/decoders/noop.go.tmpl post_create: templates/terraform/post_create/kms_secret_ciphertext.go.tmpl diff --git a/mmv1/products/memorystore/Instance.yaml b/mmv1/products/memorystore/Instance.yaml index f31da1ce1fde..b29f279c7f3e 100644 --- a/mmv1/products/memorystore/Instance.yaml +++ b/mmv1/products/memorystore/Instance.yaml @@ -40,7 +40,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/memorystore_instance.go.tmpl' decoder: 'templates/terraform/decoders/memorystore_instance.go.tmpl' diff --git a/mmv1/products/monitoring/MonitoredProject.yaml b/mmv1/products/monitoring/MonitoredProject.yaml index 891bb5c83036..8380e7b3dc1d 100644 --- a/mmv1/products/monitoring/MonitoredProject.yaml +++ b/mmv1/products/monitoring/MonitoredProject.yaml @@ -34,7 +34,6 @@ async: actions: ['create', 'delete'] operation: base_url: '{{op_id}}' -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/monitoring_monitored_project.go.tmpl' test_constants: 'templates/terraform/test_constants/monitoring_monitored_project.go.tmpl' diff --git a/mmv1/products/monitoring/NotificationChannel.yaml b/mmv1/products/monitoring/NotificationChannel.yaml index 196015871c0f..c973f860f5d0 100644 --- a/mmv1/products/monitoring/NotificationChannel.yaml +++ b/mmv1/products/monitoring/NotificationChannel.yaml @@ -49,7 +49,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 include_in_tgc_next: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/monitoring_notification_channel.go.tmpl' encoder: 'templates/terraform/encoders/monitoring_notification_channel.go.tmpl' diff --git a/mmv1/products/osconfig/PatchDeployment.yaml b/mmv1/products/osconfig/PatchDeployment.yaml index b347ef3caf82..91631d42ba1b 100644 --- a/mmv1/products/osconfig/PatchDeployment.yaml +++ b/mmv1/products/osconfig/PatchDeployment.yaml @@ -27,7 +27,6 @@ create_url: projects/{{project}}/patchDeployments?patchDeploymentId={{patch_depl import_format: - '{{project}} {{name}}' - '{{name}}' -flatten_all_in_method: true custom_code: encoder: templates/terraform/encoders/os_config_patch_deployment.go.tmpl decoder: templates/terraform/decoders/os_config_patch_deployment.go.tmpl diff --git a/mmv1/products/privateca/CaPool.yaml b/mmv1/products/privateca/CaPool.yaml index 5c28f42e04b0..c94d9fe272bf 100644 --- a/mmv1/products/privateca/CaPool.yaml +++ b/mmv1/products/privateca/CaPool.yaml @@ -47,7 +47,6 @@ iam_policy: parent_resource_attribute: 'ca_pool' iam_conditions_request_type: 'QUERY_PARAM_NESTED' example_config_body: 'templates/terraform/iam/example_config_body/privateca_ca_pool.tf.tmpl' -flatten_all_in_method: true custom_code: tgc_decoder: 'templates/tgc_next/decoders/privateca_capool.go.tmpl' examples: diff --git a/mmv1/products/privateca/CertificateAuthority.yaml b/mmv1/products/privateca/CertificateAuthority.yaml index f3aa99c0ba6c..513ec47fe234 100644 --- a/mmv1/products/privateca/CertificateAuthority.yaml +++ b/mmv1/products/privateca/CertificateAuthority.yaml @@ -45,7 +45,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/privateca_certificate_authority.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/redis/Cluster.yaml b/mmv1/products/redis/Cluster.yaml index ee8ec507fd91..dcbca567bbf1 100644 --- a/mmv1/products/redis/Cluster.yaml +++ b/mmv1/products/redis/Cluster.yaml @@ -116,7 +116,6 @@ async: result: resource_inside_response: false include_in_tgc_next: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/redis_cluster.go.tmpl' decoder: 'templates/terraform/decoders/redis_cluster.go.tmpl' diff --git a/mmv1/products/redis/Instance.yaml b/mmv1/products/redis/Instance.yaml index 62bfd9f0b4c3..d317a3ab5e2d 100644 --- a/mmv1/products/redis/Instance.yaml +++ b/mmv1/products/redis/Instance.yaml @@ -38,7 +38,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: false -flatten_all_in_method: true custom_code: extra_schema_entry: 'templates/terraform/extra_schema_entry/redis_instance.tmpl' constants: 'templates/terraform/constants/redis_instance.go.tmpl' diff --git a/mmv1/products/resourcemanager/Lien.yaml b/mmv1/products/resourcemanager/Lien.yaml index 18eef62504bd..5336c0c33393 100644 --- a/mmv1/products/resourcemanager/Lien.yaml +++ b/mmv1/products/resourcemanager/Lien.yaml @@ -44,7 +44,6 @@ nested_query: - liens is_list_of_ids: false modify_by_patch: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/resourcemanager_lien.go.tmpl' test_constants: 'templates/terraform/constants/resourcemanager_lien.go.tpml' diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index 62b86082b9bf..e113134f5477 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -26,7 +26,6 @@ base_url: 'projects/{{project}}/secrets' self_link: 'projects/{{project}}/secrets/{{secret_id}}' create_url: 'projects/{{project}}/secrets?secretId={{secret_id}}' update_verb: 'PATCH' -flatten_all_in_method: true update_mask: true import_format: - 'projects/{{project}}/secrets/{{secret_id}}' diff --git a/mmv1/products/secretmanager/SecretVersion.yaml b/mmv1/products/secretmanager/SecretVersion.yaml index 21077c8d322b..164643375de9 100644 --- a/mmv1/products/secretmanager/SecretVersion.yaml +++ b/mmv1/products/secretmanager/SecretVersion.yaml @@ -41,7 +41,6 @@ timeouts: delete_minutes: 20 include_in_tgc_next: true cai_asset_name_format: '{{secret}}/versions/{{version}}' -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_destroyed_state_as_gone.tmpl' pre_create: 'templates/terraform/pre_create/secret_manager_secret_version.go.tmpl' diff --git a/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml b/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml index 48b6590e8e75..30d5b1289d65 100644 --- a/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml +++ b/mmv1/products/secretmanagerregional/RegionalSecretVersion.yaml @@ -38,7 +38,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_destroyed_state_as_gone.tmpl' pre_create: 'templates/terraform/pre_create/secret_manager_regional_secret_version.go.tmpl' diff --git a/mmv1/products/servicedirectory/Endpoint.yaml b/mmv1/products/servicedirectory/Endpoint.yaml index e1443f8dbf5d..af189501b797 100644 --- a/mmv1/products/servicedirectory/Endpoint.yaml +++ b/mmv1/products/servicedirectory/Endpoint.yaml @@ -30,7 +30,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: custom_import: 'templates/terraform/custom_import/service_directory_endpoint.go.tmpl' encoder: 'templates/terraform/encoders/service_directory_metadata_to_annotations.go.tmpl' diff --git a/mmv1/products/spanner/BackupSchedule.yaml b/mmv1/products/spanner/BackupSchedule.yaml index 3a0e4598a6f7..485c6f739bac 100644 --- a/mmv1/products/spanner/BackupSchedule.yaml +++ b/mmv1/products/spanner/BackupSchedule.yaml @@ -41,7 +41,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/spanner_schedule_backup.go.tmpl' decoder: 'templates/terraform/decoders/spanner_schedule_backup.go.tmpl' diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index dd99b1016c43..a8e189ed4bde 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -51,7 +51,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/spanner_database.go.tmpl' encoder: 'templates/terraform/encoders/spanner_database.go.tmpl' diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 828cc7a1a83f..92f36024888e 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -31,7 +31,6 @@ import_format: cai_asset_name_format: 'projects/{{project}}/instances/{{name}}' include_in_tgc_next: true -flatten_all_in_method: true timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/products/spanner/InstanceConfig.yaml b/mmv1/products/spanner/InstanceConfig.yaml index 7241e4913320..d1c00291d72f 100644 --- a/mmv1/products/spanner/InstanceConfig.yaml +++ b/mmv1/products/spanner/InstanceConfig.yaml @@ -34,7 +34,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 autogen_async: true -flatten_all_in_method: true async: actions: ['create', 'update'] type: 'OpAsync' diff --git a/mmv1/products/sql/Database.yaml b/mmv1/products/sql/Database.yaml index 5aa96e034866..4f5029b530a4 100644 --- a/mmv1/products/sql/Database.yaml +++ b/mmv1/products/sql/Database.yaml @@ -38,7 +38,6 @@ async: result: resource_inside_response: false collection_url_key: 'items' -flatten_all_in_method: true custom_code: pre_read: 'templates/terraform/pre_read/sql_database_activation_policy.tmpl' # Sweeper skipped as this resource has customized deletion. diff --git a/mmv1/products/sql/SourceRepresentationInstance.yaml b/mmv1/products/sql/SourceRepresentationInstance.yaml index ae043a08c6b1..2317b23c2f11 100644 --- a/mmv1/products/sql/SourceRepresentationInstance.yaml +++ b/mmv1/products/sql/SourceRepresentationInstance.yaml @@ -22,6 +22,20 @@ description: | affect billing. You cannot update the source representation instance. base_url: projects/{{project}}/instances immutable: true +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: 'projects/{{project}}/operations/{{op_id}}' + result: + resource_inside_response: false +custom_code: + encoder: 'templates/terraform/encoders/sql_source_representation_instance.go.tmpl' + decoder: 'templates/terraform/decoders/sql_source_representation_instance.go.tmpl' kind: sql#instance id_format: projects/{{project}}/instances/{{name}} sweeper: @@ -58,7 +72,7 @@ properties: type: String required: true description: | - The MySQL, PostgreSQL or SQL Server (beta) version to use. Supported values include MYSQL_5_6, MYSQL_5_7, MYSQL_8_0, MYSQL_8_4, POSTGRES_9_6, POSTGRES_10, POSTGRES_11, POSTGRES_12, POSTGRES_13, POSTGRES_14, POSTGRES_15, POSTGRES_16, POSTGRES_17, POSTGRES_18, SQLSERVER_2022_STANDARD, SQLSERVER_2022_ENTERPRISE, SQLSERVER_2022_EXPRESS, SQLSERVER_2022_WEB, SQLSERVER_2025_STANDARD, SQLSERVER_2025_ENTERPRISE, SQLSERVER_2025_EXPRESS, SQLSERVER_2025_WEB. Database Version Policies includes an up-to-date reference of supported versions. + The MySQL, PostgreSQL or SQL Server (beta) version to use. Supported values include MYSQL_5_6, MYSQL_5_7, MYSQL_8_0, MYSQL_8_4, POSTGRES_9_6, POSTGRES_10, POSTGRES_11, POSTGRES_12, POSTGRES_13, POSTGRES_14, POSTGRES_15, POSTGRES_16, POSTGRES_17, POSTGRES_18. Database Version Policies includes an up-to-date reference of supported versions. - name: onPremisesConfiguration type: NestedObject required: true diff --git a/mmv1/products/storage/HmacKey.yaml b/mmv1/products/storage/HmacKey.yaml index bd5e933802f0..1df033b441f1 100644 --- a/mmv1/products/storage/HmacKey.yaml +++ b/mmv1/products/storage/HmacKey.yaml @@ -47,7 +47,6 @@ async: suppress_error: false target_occurrences: 1 actions: ['create'] -flatten_all_in_method: true custom_code: decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' post_create: 'templates/terraform/post_create/storage_hmac_key.go.tmpl' diff --git a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml index fdcd37c7dfc2..9692370bf120 100644 --- a/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml +++ b/mmv1/products/vertexai/IndexEndpointDeployedIndex.yaml @@ -46,7 +46,6 @@ async: result: resource_inside_response: true include_project: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/vertex_ai_index_endpoint_deployed_index.go.tmpl' update_encoder: 'templates/terraform/update_encoder/vertex_ai_index_endpoint_deployed_index.go.tmpl' diff --git a/mmv1/products/vmwareengine/PrivateCloud.yaml b/mmv1/products/vmwareengine/PrivateCloud.yaml index 14239dfd65f1..4eedf7fe0504 100644 --- a/mmv1/products/vmwareengine/PrivateCloud.yaml +++ b/mmv1/products/vmwareengine/PrivateCloud.yaml @@ -41,7 +41,6 @@ async: delete_minutes: 150 result: resource_inside_response: false -flatten_all_in_method: true custom_code: constants: 'templates/terraform/constants/vmwareengine_private_cloud.go.tmpl' update_encoder: 'templates/terraform/update_encoder/private_cloud.go.tmpl' diff --git a/mmv1/products/vpcaccess/Connector.yaml b/mmv1/products/vpcaccess/Connector.yaml index 7bfa931a20a6..45a737196666 100644 --- a/mmv1/products/vpcaccess/Connector.yaml +++ b/mmv1/products/vpcaccess/Connector.yaml @@ -38,7 +38,6 @@ async: base_url: '{{op_id}}' result: resource_inside_response: true -flatten_all_in_method: true custom_code: encoder: 'templates/terraform/encoders/no_send_name.go.tmpl' decoder: 'templates/terraform/decoders/long_name_to_self_link.go.tmpl' From 1e3347355179b8814d5c1ea34e0619e6862cd299 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 8 Apr 2026 10:28:23 -0700 Subject: [PATCH 027/100] cleanup after merge-conflict resolution --- .../iambeta/WorkloadIdentityPool.yaml | 1 - mmv1/products/spanner/Instance.yaml | 1 - .../sql/SourceRepresentationInstance.yaml | 20 ++++++------------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/mmv1/products/iambeta/WorkloadIdentityPool.yaml b/mmv1/products/iambeta/WorkloadIdentityPool.yaml index 78bd8e249393..3b900e491c81 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPool.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPool.yaml @@ -52,7 +52,6 @@ iam_policy: - '{{workload_identity_pool_id}}' allowed_iam_role: 'roles/iam.workloadIdentityPoolViewer' iam_conditions_request_type: 'REQUEST_BODY' - min_version: beta custom_code: constants: 'templates/terraform/constants/iam_workload_identity_pool.go.tmpl' decoder: 'templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl' diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 92f36024888e..95053fa49e9f 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -30,7 +30,6 @@ import_format: - '{{name}}' cai_asset_name_format: 'projects/{{project}}/instances/{{name}}' include_in_tgc_next: true - timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/products/sql/SourceRepresentationInstance.yaml b/mmv1/products/sql/SourceRepresentationInstance.yaml index 2317b23c2f11..c32b6d9c6cd2 100644 --- a/mmv1/products/sql/SourceRepresentationInstance.yaml +++ b/mmv1/products/sql/SourceRepresentationInstance.yaml @@ -22,20 +22,6 @@ description: | affect billing. You cannot update the source representation instance. base_url: projects/{{project}}/instances immutable: true -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -async: - actions: ['create', 'delete', 'update'] - type: 'OpAsync' - operation: - base_url: 'projects/{{project}}/operations/{{op_id}}' - result: - resource_inside_response: false -custom_code: - encoder: 'templates/terraform/encoders/sql_source_representation_instance.go.tmpl' - decoder: 'templates/terraform/decoders/sql_source_representation_instance.go.tmpl' kind: sql#instance id_format: projects/{{project}}/instances/{{name}} sweeper: @@ -43,6 +29,12 @@ sweeper: field: settings.deletionProtectionEnabled value: "false" include_full_resource: true +async: + operation: + base_url: projects/{{project}}/operations/{{op_id}} +custom_code: + encoder: templates/terraform/encoders/sql_source_representation_instance.go.tmpl + decoder: templates/terraform/decoders/sql_source_representation_instance.go.tmpl examples: - name: sql_source_representation_instance_basic primary_resource_id: instance From d4ee95a0c5f2a0d14e32f01c2fb9c776a93b1e42 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 12:43:53 -0700 Subject: [PATCH 028/100] resolve diffs from rebase to magic-modules/main --- mmv1/products/iambeta/WorkloadIdentityPool.yaml | 9 +++++++++ mmv1/products/sql/SourceRepresentationInstance.yaml | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mmv1/products/iambeta/WorkloadIdentityPool.yaml b/mmv1/products/iambeta/WorkloadIdentityPool.yaml index 3b900e491c81..3da493bab266 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPool.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPool.yaml @@ -277,6 +277,15 @@ properties: PEM certificate of the PKI used for validation. Must only contain one ca certificate(either root or intermediate cert). required: true + - name: 'trustDefaultSharedCa' + type: Boolean + description: | + If set to True, the trust bundle will include the private ca managed identity regional root + public certificates. + + + ~> **Note** `trust_default_shared_ca` is only supported for managed identity trust domain + resource. - name: 'attestationRules' is_missing_in_cai: true type: Array diff --git a/mmv1/products/sql/SourceRepresentationInstance.yaml b/mmv1/products/sql/SourceRepresentationInstance.yaml index c32b6d9c6cd2..77fa167baa41 100644 --- a/mmv1/products/sql/SourceRepresentationInstance.yaml +++ b/mmv1/products/sql/SourceRepresentationInstance.yaml @@ -64,7 +64,7 @@ properties: type: String required: true description: | - The MySQL, PostgreSQL or SQL Server (beta) version to use. Supported values include MYSQL_5_6, MYSQL_5_7, MYSQL_8_0, MYSQL_8_4, POSTGRES_9_6, POSTGRES_10, POSTGRES_11, POSTGRES_12, POSTGRES_13, POSTGRES_14, POSTGRES_15, POSTGRES_16, POSTGRES_17, POSTGRES_18. Database Version Policies includes an up-to-date reference of supported versions. + The MySQL, PostgreSQL or SQL Server (beta) version to use. Supported values include MYSQL_5_6, MYSQL_5_7, MYSQL_8_0, MYSQL_8_4, POSTGRES_9_6, POSTGRES_10, POSTGRES_11, POSTGRES_12, POSTGRES_13, POSTGRES_14, POSTGRES_15, POSTGRES_16, POSTGRES_17, POSTGRES_18, SQLSERVER_2022_STANDARD, SQLSERVER_2022_ENTERPRISE, SQLSERVER_2022_EXPRESS, SQLSERVER_2022_WEB, SQLSERVER_2025_STANDARD, SQLSERVER_2025_ENTERPRISE, SQLSERVER_2025_EXPRESS, SQLSERVER_2025_WEB. Database Version Policies includes an up-to-date reference of supported versions. - name: onPremisesConfiguration type: NestedObject required: true From 69d0921ce5c43639ee4aa996a469b5750f5b8697 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 8 Apr 2026 14:01:21 -0700 Subject: [PATCH 029/100] add Get default provider values in list_metadata.go --- .../terraform/tpgresource/list_resource.go | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index 2dec34b042aa..e37824ab7867 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -248,3 +248,36 @@ func (listR *ListResourceMetadata) SetResult(ctx context.Context, includeResourc return nil } + +// ResolveProject returns the project from override if it is set and non-empty, +// otherwise falls back to the provider-level default. +func (r *ListResourceMetadata) GetProject(override types.String) string { + if !override.IsNull() && !override.IsUnknown() { + if v := override.ValueString(); v != "" { + return v + } + } + return r.ProjectId +} + +// ResolveRegion returns the region from override if it is set and non-empty, +// otherwise falls back to the provider-level default. +func (r *ListResourceMetadata) GetRegion(override types.String) string { + if !override.IsNull() && !override.IsUnknown() { + if v := override.ValueString(); v != "" { + return v + } + } + return r.Region +} + +// ResolveZone returns the zone from override if it is set and non-empty, +// otherwise falls back to the provider-level default. +func (r *ListResourceMetadata) GetZone(override types.String) string { + if !override.IsNull() && !override.IsUnknown() { + if v := override.ValueString(); v != "" { + return v + } + } + return r.Zone +} From 4eb8f08059f955aac928ea712986012788bbd240 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 8 Apr 2026 18:56:17 -0700 Subject: [PATCH 030/100] move identity set logic to its own SetIdentityFields method --- .../terraform/tpgresource/list_resource.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index e37824ab7867..f80dc23d62d8 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -281,3 +281,23 @@ func (r *ListResourceMetadata) GetZone(override types.String) string { } return r.Zone } + +func SetIdentityFields(ctx context.Context, result *list.ListResult, rd *schema.ResourceData, fields map[string]string) error { + identity, err := rd.Identity() + if err != nil { + return fmt.Errorf("error getting identity: %s", err) + } + for k, v := range fields { + if err := identity.Set(k, v); err != nil { + return fmt.Errorf("error setting identity field %q: %s", k, err) + } + } + tfTypeIdentity, err := rd.TfTypeIdentityState() + if err != nil { + return err + } + if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil { + return errors.New("error setting identity") + } + return nil +} From 7c0db649cdd5604fc211bd15b2e709e08415552e Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 5 Dec 2025 11:49:14 -0800 Subject: [PATCH 031/100] initial run generation WIP --- .../templates/terraform/list_resource.go.tmpl | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 mmv1/templates/terraform/list_resource.go.tmpl diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl new file mode 100644 index 000000000000..beb576a7bf60 --- /dev/null +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -0,0 +1,111 @@ +{{/*# The license inside this block applies to this file. + # Copyright 2024 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +*/}} +var _ tpgresource.ListResourceWithRawV5Schemas = &{{ $.ResourceName -}}ListResource{} + +type {{ $.ResourceName -}}ListResource struct { + tpgresource.ListResourceMetadata +} + +func New{{ $.ResourceName -}}ListResource() list.ListResource { + return &{{ $.ResourceName -}}ListResource{} +} + +func (r *{{ $.ResourceName -}}ListResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "google_{{ $.ProductMetadata.TerraformName -}}_{{ $.Name -}}" +} + +func (r *{{ $.ResourceName -}}ListResource) RawV5Schemas(ctx context.Context, _ list.RawV5SchemaRequest, resp *list.RawV5SchemaResponse) { + {{ $.ResourceName -}} := Resource{{ $.ResourceName -}}() + resp.ProtoV5Schema = {{ $.ResourceName -}}.ProtoSchema(ctx)() + resp.ProtoV5IdentitySchema = {{ $.ResourceName -}}.ProtoIdentitySchema(ctx)() +} + +func (r *{{ $.ResourceName -}}ListResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + r.Defaults(req, resp) +} + +func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) { + resp.Schema = listschema.Schema{ + Attributes: map[string]listschema.Attribute{ + {{- range $identity := $.IdentityProperties }} + "{{ $identity.Name }}": listschema.StringAttribute{ + Optional: true, + }, + {{- end }} + }, + } +} + +type {{ $.ResourceName -}}ListModel struct { + {{- range $identity := $.IdentityProperties }} + {{ $identity.Name }} string `tfsdk:"{{ $identity.Name }}"` + {{- end }} +} + +func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { + var data {{ $.ResourceName -}}ListModel + diags := req.Config.Get(ctx, &data) + if diags.HasError() { + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + + /* INSERT IDENTITY SETTING GENERATION CODE HERE */ + + + stream.Results = func(push func(list.ListResult) bool) { + client := r.Client.New{{ $.ResourceName -}}sClient(r.Client.UserAgent) + + listReq := client.{{ $.ResourceName -}}.List{{ $.Name -}}s(project, zone) + + if err := listReq.Pages(ctx, func(page *{{ lower $.ProductMetadata.Name }}.{{ $.ResourceName -}}List) error { + log.Printf("[DEBUG] {{ $.ResourceName -}} list: %v", page.Items) + for _, {{ $.ResourceName -}} := range page.Items { + result := req.NewListResult(ctx) + result.DisplayName = {{ $.ResourceName -}}.Name + + {{ $.ResourceName -}}Resource := Resource{{ $.ResourceName -}}() + rd := {{ $.ResourceName -}}Resource.Data(&terraform.InstanceState{}) + rd.SetId({{ $.ResourceName -}}.Name) + + /* INSERT IDENTITY SETTING GENERATION CODE HERE */ + + tfTypeIdentity, err := rd.TfTypeIdentityState() + if err != nil { + return err + } + if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil { + return errors.New("error setting identity") + } + + tfTypeResource, err := rd.TfTypeResourceState() + if err != nil { + return err + } + if err := result.Resource.Set(ctx, *tfTypeResource); err != nil { + return errors.New("error setting resource") + } + + if !push(result) { + return errors.New("stream closed") + } + } + return nil + }); err != nil { + diags.AddError("API Error", err.Error()) + } + stream.Results = list.ListResultsStreamDiagnostics(diags) + } +} \ No newline at end of file From 778153edd2fbc2e26922e77c636764067644a8de Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 9 Dec 2025 08:31:13 -0800 Subject: [PATCH 032/100] move generation of list resource to be its own file instead of within resource file --- mmv1/provider/template_data.go | 1 + mmv1/provider/terraform.go | 4 ++ .../templates/terraform/list_resource.go.tmpl | 52 ++++++++++++------- mmv1/templates/terraform/resource.go.tmpl | 6 +++ 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index 55183ca1d1fe..4a5a39d4bacb 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -63,6 +63,7 @@ func (td *TemplateData) GenerateResourceFile(filePath string, resource api.Resou "templates/terraform/update_mask.go.tmpl", "templates/terraform/nested_query.go.tmpl", "templates/terraform/unordered_list_customize_diff.go.tmpl", + "templates/terraform/list_resource.go.tmpl", } td.GenerateFile(filePath, templatePath, resource, true, templates...) } diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 7731668970f1..a6ec715b35bd 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -155,6 +155,10 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s.go", t.ResourceGoFilename(object))) templateData.GenerateResourceFile(targetFilePath, object) } + if object.GenerateListResource { + targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_resource_%s.go", t.ResourceGoFilename(object))) + templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, "templates/terraform/list_resource.go.tmpl") + } } if generateDocs { diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index beb576a7bf60..4092b9a9d8af 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -68,44 +68,58 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L stream.Results = func(push func(list.ListResult) bool) { client := r.Client.New{{ $.ResourceName -}}sClient(r.Client.UserAgent) - listReq := client.{{ $.ResourceName -}}.List{{ $.Name -}}s(project, zone) + listReq := {{lower $.ProductMetadata.Name }}.List{{ $.Name -}}sRequest{ + {{- range $identity := $.IdentityProperties }} + {{ $identity.Name }}, + {{- end }} + } + + it := client.List{{ $.Name -}}s(ctx, &listReq) + - if err := listReq.Pages(ctx, func(page *{{ lower $.ProductMetadata.Name }}.{{ $.ResourceName -}}List) error { - log.Printf("[DEBUG] {{ $.ResourceName -}} list: %v", page.Items) - for _, {{ $.ResourceName -}} := range page.Items { - result := req.NewListResult(ctx) - result.DisplayName = {{ $.ResourceName -}}.Name + for { + resp, err := it.Next() + if err == iterator.Done { + break + } else if err != nil { + diags.AddError("API Error", err.Error()) + break + } + + result := req.NewListResult(ctx) + result.DisplayName = resp.Name - {{ $.ResourceName -}}Resource := Resource{{ $.ResourceName -}}() - rd := {{ $.ResourceName -}}Resource.Data(&terraform.InstanceState{}) - rd.SetId({{ $.ResourceName -}}.Name) + {{ $.ResourceName -}}Resource := Resource{{ $.ResourceName -}}() + rd := {{ $.ResourceName -}}Resource.Data(&terraform.InstanceState{}) + rd.SetId(resp.Name) - /* INSERT IDENTITY SETTING GENERATION CODE HERE */ + /* INSERT IDENTITY SETTING GENERATION CODE HERE */ tfTypeIdentity, err := rd.TfTypeIdentityState() if err != nil { - return err + diags.AddError("error getting identity state", err.Error()) + break } if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil { - return errors.New("error setting identity") + diags = err + break } tfTypeResource, err := rd.TfTypeResourceState() if err != nil { - return err + diags.AddError("error getting resource state", err.Error()) + break } if err := result.Resource.Set(ctx, *tfTypeResource); err != nil { - return errors.New("error setting resource") + diags = err + break } if !push(result) { - return errors.New("stream closed") + diags.AddError("stream closed", "stream closed") + break } } - return nil - }); err != nil { - diags.AddError("API Error", err.Error()) - } stream.Results = list.ListResultsStreamDiagnostics(diags) } } \ No newline at end of file diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index 9e5f4edca5c0..eb985850ab6a 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -36,6 +36,12 @@ import ( "time" "github.com/hashicorp/errwrap" + {{ if $.GenerateListResource -}} + "github.com/hashicorp/terraform-plugin-framework/list" + listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" + "github.com/hashicorp/terraform-plugin-framework/resource" + {{ lower $.ProductMetadata.Name }} "cloud.google.com/go/run/apiv2/pb" + {{ end -}} "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" From 978d3c28143f943bb52a229a73e65b8874d3447f Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 12 Dec 2025 19:24:54 -0800 Subject: [PATCH 033/100] pseudocode list_resource --- .../templates/terraform/list_resource.go.tmpl | 75 ++++++++++++++----- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 4092b9a9d8af..ce1e88815ffa 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -12,6 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. */}} + +package {{ lower $.ProductMetadata.Name }} + +import ( + "context" + + cloudrun "cloud.google.com/go/run/apiv2/runpb" // This shouldn't be from the cloud pkg but instead an internal package within magicmodules (e.g tpgresource/...) + "github.com/hashicorp/terraform-plugin-framework/list" + listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "google.golang.org/api/iterator" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + var _ tpgresource.ListResourceWithRawV5Schemas = &{{ $.ResourceName -}}ListResource{} type {{ $.ResourceName -}}ListResource struct { @@ -43,7 +59,13 @@ func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context "{{ $identity.Name }}": listschema.StringAttribute{ Optional: true, }, - {{- end }} + {{- end }}, + ~> we need logic to determine whether we can add filter support here or not + + "filter": listschema.StringAttribute{ + Optional: true, + }, + }, } } @@ -54,29 +76,27 @@ type {{ $.ResourceName -}}ListModel struct { {{- end }} } -func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { - var data {{ $.ResourceName -}}ListModel - diags := req.Config.Get(ctx, &data) - if diags.HasError() { - stream.Results = list.ListResultsStreamDiagnostics(diags) - return - } - - /* INSERT IDENTITY SETTING GENERATION CODE HERE */ - - - stream.Results = func(push func(list.ListResult) bool) { +{{ if $.CustomListMethod }} + {{ $.CustomTemplate $.CustomListMethod false -}} +{{ else }} + func List{{ $.ResourceName -}}s(ctx context.Context, req list.ListRequest) { client := r.Client.New{{ $.ResourceName -}}sClient(r.Client.UserAgent) - listReq := {{lower $.ProductMetadata.Name }}.List{{ $.Name -}}sRequest{ + listReq := {{lower $.ProductMetadata.Name }}.List{{ $.Name -}}sRequest{ + {{if $.NonParent }} + Parent: {{ $.ParentResourceName}}, + {{else}} {{- range $identity := $.IdentityProperties }} - {{ $identity.Name }}, + {{ $identity.Name }}: data.{{ $identity.Name }}, {{- end }} + {{ if not (or $.ExcludeFilter $.CustomFilter) -}} + Filter: data.Filter + {{ end }} + {{ end }} } it := client.List{{ $.Name -}}s(ctx, &listReq) - for { resp, err := it.Next() if err == iterator.Done { @@ -86,6 +106,25 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L break } + } + } +{{ end }} + +func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { + var data {{ $.ResourceName -}}ListModel + diags := req.Config.Get(ctx, &data) + if diags.HasError() { + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + + /* INSERT IDENTITY SETTING GENERATION CODE HERE */ + + + stream.Results = func(push func(list.ListResult) bool) { + + LIST METHOD (func(){ + result := req.NewListResult(ctx) result.DisplayName = resp.Name @@ -120,6 +159,8 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L break } } + + )} + stream.Results = list.ListResultsStreamDiagnostics(diags) } -} \ No newline at end of file From 6579a8c09cdbbfb7e2f543d6a6791ca1675c84e6 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 16 Dec 2025 11:32:49 -0800 Subject: [PATCH 034/100] WIP --- .../templates/terraform/list_resource.go.tmpl | 4 +- mmv1/templates/terraform/resource.go.tmpl | 4 - .../terraform/transport/cloud_clients.go.tmpl | 166 ++++++++++++++++++ 3 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 mmv1/third_party/terraform/transport/cloud_clients.go.tmpl diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index ce1e88815ffa..f7b750f690fa 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -18,7 +18,7 @@ package {{ lower $.ProductMetadata.Name }} import ( "context" - cloudrun "cloud.google.com/go/run/apiv2/runpb" // This shouldn't be from the cloud pkg but instead an internal package within magicmodules (e.g tpgresource/...) + // This shouldn't be from the cloud pkg but instead an internal package within magicmodules (e.g tpgresource/...) "github.com/hashicorp/terraform-plugin-framework/list" listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -55,7 +55,7 @@ func (r *{{ $.ResourceName -}}ListResource) Configure(_ context.Context, req res func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) { resp.Schema = listschema.Schema{ Attributes: map[string]listschema.Attribute{ - {{- range $identity := $.IdentityProperties }} + {{- range $identity := $.IdentityProperties }} // we can't rely on this because of some resources not containing all the possible parent combinations for list, we should rely more on `base_url` "{{ $identity.Name }}": listschema.StringAttribute{ Optional: true, }, diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index eb985850ab6a..d8fae49fc4d5 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -37,10 +37,6 @@ import ( "github.com/hashicorp/errwrap" {{ if $.GenerateListResource -}} - "github.com/hashicorp/terraform-plugin-framework/list" - listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" - "github.com/hashicorp/terraform-plugin-framework/resource" - {{ lower $.ProductMetadata.Name }} "cloud.google.com/go/run/apiv2/pb" {{ end -}} "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" diff --git a/mmv1/third_party/terraform/transport/cloud_clients.go.tmpl b/mmv1/third_party/terraform/transport/cloud_clients.go.tmpl new file mode 100644 index 000000000000..03b70c9cf2d5 --- /dev/null +++ b/mmv1/third_party/terraform/transport/cloud_clients.go.tmpl @@ -0,0 +1,166 @@ +package transport + +import ( + "log" + + // cloud.google.com/go packages - All available Google Cloud products + // Reference: https://docs.cloud.google.com/go/docs/reference + // Only packages listed in the official documentation are included + + // Access & Security + accessapproval "cloud.google.com/go/accessapproval/apiv1" + accesscontextmanager "cloud.google.com/go/accesscontextmanager/apiv1" + binaryauthorization "cloud.google.com/go/binaryauthorization/apiv1" + iam "cloud.google.com/go/iam" + iamcredentials "cloud.google.com/go/iam/credentials/apiv1" + iap "cloud.google.com/go/iap/apiv1" + orgpolicy "cloud.google.com/go/orgpolicy/apiv2" + recaptchaenterprise "cloud.google.com/go/recaptchaenterprise/v2/apiv1" + securitycenter "cloud.google.com/go/securitycenter/apiv1" + securitycentermanagement "cloud.google.com/go/securitycentermanagement/apiv1" + + // AI & Machine Learning + aiplatform "cloud.google.com/go/aiplatform/apiv1" + automl "cloud.google.com/go/automl/apiv1" + documentai "cloud.google.com/go/documentai/apiv1" + language "cloud.google.com/go/language/apiv1" + languagev2 "cloud.google.com/go/language/apiv2" + speech "cloud.google.com/go/speech/apiv1" + speechv2 "cloud.google.com/go/speech/apiv2" + texttospeech "cloud.google.com/go/texttospeech/apiv1" + translate "cloud.google.com/go/translate/apiv3" + videointelligence "cloud.google.com/go/videointelligence/apiv1" + vision "cloud.google.com/go/vision/apiv1" + visionv2 "cloud.google.com/go/vision/v2/apiv1" + + // Analytics & Data + bigquery "cloud.google.com/go/bigquery" + datacatalog "cloud.google.com/go/datacatalog/apiv1" + dataplex "cloud.google.com/go/dataplex/apiv1" + datastore "cloud.google.com/go/datastore" + + // Application Development + appengine "cloud.google.com/go/appengine/apiv1" + cloudbuild "cloud.google.com/go/cloudbuild/apiv1" + cloudrun "cloud.google.com/go/run/apiv2" + scheduler "cloud.google.com/go/scheduler/apiv1" + + // Compute & Infrastructure + baremetalsolution "cloud.google.com/go/baremetalsolution/apiv2" + compute "cloud.google.com/go/compute/apiv1" + container "cloud.google.com/go/container/apiv1" + edgecontainer "cloud.google.com/go/edgecontainer/apiv1" + edgenetwork "cloud.google.com/go/edgenetwork/apiv1" + filestore "cloud.google.com/go/filestore/apiv1" + tpu "cloud.google.com/go/tpu/apiv1" + vmmigration "cloud.google.com/go/vmmigration/apiv1" + vmwareengine "cloud.google.com/go/vmwareengine/apiv1" + vpcaccess "cloud.google.com/go/vpcaccess/apiv1" + + // Databases + alloydb "cloud.google.com/go/alloydb/apiv1" + bigtable "cloud.google.com/go/bigtable" + datastream "cloud.google.com/go/datastream/apiv1" + firestore "cloud.google.com/go/firestore" + memcache "cloud.google.com/go/memcache/apiv1" + metastore "cloud.google.com/go/metastore/apiv1" + metastorealpha "cloud.google.com/go/metastore/apiv1alpha" + metastorebeta "cloud.google.com/go/metastore/apiv1beta" + redis "cloud.google.com/go/redis/apiv1" + spanner "cloud.google.com/go/spanner" + + // Developer Tools + artifactregistry "cloud.google.com/go/artifactregistry/apiv1" + clouddms "cloud.google.com/go/clouddms/apiv1" + cloudquotas "cloud.google.com/go/cloudquotas/apiv1" + deploy "cloud.google.com/go/deploy/apiv1" + gsuiteaddons "cloud.google.com/go/gsuiteaddons/apiv1" + orchestration "cloud.google.com/go/orchestration/airflow/service/apiv1" + servicemanagement "cloud.google.com/go/servicemanagement/apiv1" + serviceusage "cloud.google.com/go/serviceusage/apiv1" + + // Identity & Directory + managedidentities "cloud.google.com/go/managedidentities/apiv1" + oslogin "cloud.google.com/go/oslogin/apiv1" + + // Management & Operations + asset "cloud.google.com/go/asset/apiv1" + billing "cloud.google.com/go/billing/apiv1" + cloudcontrolspartner "cloud.google.com/go/cloudcontrolspartner/apiv1" + essentialcontacts "cloud.google.com/go/essentialcontacts/apiv1" + logging "cloud.google.com/go/logging/apiv2" + osconfig "cloud.google.com/go/osconfig/apiv1" + policysimulator "cloud.google.com/go/policysimulator/apiv1" + policytroubleshooter "cloud.google.com/go/policytroubleshooter/apiv1" + recommender "cloud.google.com/go/recommender/apiv1" + resourcesettings "cloud.google.com/go/resourcesettings/apiv1" + servicedirectory "cloud.google.com/go/servicedirectory/apiv1" + trace "cloud.google.com/go/trace/apiv2" + + // Networking + networkconnectivity "cloud.google.com/go/networkconnectivity/apiv1" + networkmanagement "cloud.google.com/go/networkmanagement/apiv1" + networkservices "cloud.google.com/go/networkservices/apiv1" + + // Storage & Transfer + storage "cloud.google.com/go/storage" + storagetransfer "cloud.google.com/go/storagetransfer/apiv1" + + // Data Processing + batch "cloud.google.com/go/batch/apiv1" + dataflow "cloud.google.com/go/dataflow/apiv1beta3" + dataform "cloud.google.com/go/dataform/apiv1beta1" + datafusion "cloud.google.com/go/datafusion/apiv1" + lifesciences "cloud.google.com/go/lifesciences/apiv2beta" + workflows "cloud.google.com/go/workflows/apiv1" + + // Media & Content + videostitcher "cloud.google.com/go/video/stitcher/apiv1" + mediatranslation "cloud.google.com/go/mediatranslation/apiv1beta1" + + // Other Services + apigeeregistry "cloud.google.com/go/apigeeregistry/apiv1" + apikeys "cloud.google.com/go/apikeys/apiv2" + assuredworkloads "cloud.google.com/go/assuredworkloads/apiv1" + certificatemanager "cloud.google.com/go/certificatemanager/apiv1" + channel "cloud.google.com/go/channel/apiv1" + cloudtasks "cloud.google.com/go/cloudtasks/apiv2" + contactcenterinsights "cloud.google.com/go/contactcenterinsights/apiv1" + containeranalysis "cloud.google.com/go/containeranalysis/apiv1" + dlp "cloud.google.com/go/dlp/apiv2" + eventarc "cloud.google.com/go/eventarc/apiv1" + gaming "cloud.google.com/go/gaming/apiv1" + gkebackup "cloud.google.com/go/gkebackup/apiv1" + gkemulticloud "cloud.google.com/go/gkemulticloud/apiv1" + ids "cloud.google.com/go/ids/apiv1" + iot "cloud.google.com/go/iot/apiv1" + kms "cloud.google.com/go/kms/apiv1" + notebooks "cloud.google.com/go/notebooks/apiv1" + optimization "cloud.google.com/go/optimization/apiv1" + parallelstore "cloud.google.com/go/parallelstore/apiv1beta" + phishingprotection "cloud.google.com/go/phishingprotection/apiv1beta1" + privatecatalog "cloud.google.com/go/privatecatalog/apiv1beta1" + pubsub "cloud.google.com/go/pubsub" + secretmanager "cloud.google.com/go/secretmanager/apiv1" + talent "cloud.google.com/go/talent/apiv4" + webrisk "cloud.google.com/go/webrisk/apiv1" + websecurityscanner "cloud.google.com/go/websecurityscanner/apiv1" + workstations "cloud.google.com/go/workstations/apiv1" + + // Legacy google.golang.org/api packages (for compatibility) + "google.golang.org/api/option" +) + +{{ range $product := $.Products }} +{{ range $resource := $product.Objects }} +func (c *Config) New{{ $product.Name }}{{ $resource.Name }}sClient() *{{underscore $product.ApiName}}.{{ $resource.Name }}Client { + log.Printf("[INFO] Instantiating {{ $product.Name }}{{ $resource.Name }} client") + client{{ $product.Name }}{{ $resource.Name }}, err := {{$product.ApiName}}.{{ $product.Name }}{{ $resource.Name }}sClient(c.Context, option.WithHTTPClient(c.Client)) + if err != nil { + log.Printf("[WARN] Error creating {{ $product.Name }}{{ $resource.Name }} client: %s", err) + return nil + } + return client{{ $product.Name }}{{ $resource.Name }} +} +{{ end }} +{{ end }} \ No newline at end of file From 352b073e7e7eea663c300acd6fb2326e0741c972 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 4 Dec 2025 13:32:37 -0800 Subject: [PATCH 035/100] initial list_resource generation support - no standarized iterator (NO BUILD) --- mmv1/api/resource.go | 3 +++ mmv1/products/cloudrun/Service.yaml | 5 +++++ mmv1/templates/terraform/resource.go.tmpl | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index bffb7033da2b..1acf71397cdd 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -245,6 +245,9 @@ type Resource struct { // EXPERIMENTAL: If true, resource should be autogenerated as a data source Datasource *resource.Datasource `yaml:"datasource_experimental,omitempty"` + // If true, generate a list resource for the resource + GenerateListResource bool `yaml:"generate_list_resource,omitempty"` + // If true, skip sweeper generation for this resource ExcludeSweeper bool `yaml:"exclude_sweeper,omitempty"` diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 6f8fe3a5cadc..1845431a77dc 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -32,7 +32,12 @@ import_format: - 'locations/{{location}}/namespaces/{{project}}/services/{{name}}' datasource_experimental: generate: true + # plural: + # generate: true + # list_function: 'templates/terraform/list_functions/cloud_run_service.go.tmpl' exclude_test: true + +generate_list_resource: true timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index d8fae49fc4d5..d89080007e3d 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -37,6 +37,9 @@ import ( "github.com/hashicorp/errwrap" {{ if $.GenerateListResource -}} + "github.com/hashicorp/terraform-plugin-framework/list" + listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" + "github.com/hashicorp/terraform-plugin-framework/resource" {{ end -}} "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -102,6 +105,10 @@ func init() { }.Register() } +{{- if $.GenerateListResource }} + {{- $.CustomTemplate "templates/terraform/list_resource.go.tmpl" false -}} +{{- end }} + func Resource{{ $.ResourceName -}}() *schema.Resource { return &schema.Resource{ Create: resource{{ $.ResourceName -}}Create, From 88c6ead7a6b0edd72caf0faa38c73ee082fe5919 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 9 Apr 2026 15:45:45 -0700 Subject: [PATCH 036/100] resolve build errors --- mmv1/products/cloudrun/Service.yaml | 2 + mmv1/provider/template_data.go | 1 - mmv1/provider/terraform.go | 8 + mmv1/provider/terraform/common~compile.yaml | 1 + mmv1/provider/terraform/common~copy.yaml | 1 + .../templates/terraform/list_resource.go.tmpl | 372 +++++++++++++----- mmv1/templates/terraform/resource.go.tmpl | 9 - 7 files changed, 296 insertions(+), 98 deletions(-) diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 1845431a77dc..672b1601c5a8 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -38,6 +38,8 @@ datasource_experimental: exclude_test: true generate_list_resource: true +# Knative-style list responses use "items" (not the default "services" key). +collection_url_key: 'items' timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index 4a5a39d4bacb..55183ca1d1fe 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -63,7 +63,6 @@ func (td *TemplateData) GenerateResourceFile(filePath string, resource api.Resou "templates/terraform/update_mask.go.tmpl", "templates/terraform/nested_query.go.tmpl", "templates/terraform/unordered_list_customize_diff.go.tmpl", - "templates/terraform/list_resource.go.tmpl", } td.GenerateFile(filePath, templatePath, resource, true, templates...) } diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index a6ec715b35bd..3e25fb5ff0ce 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -543,6 +543,10 @@ func (t Terraform) getCopyFilesInFolder(folderPath, targetDir string) map[string if di.Name() == "gha-branch-renaming.png" || di.Name() == "clock-timings-of-branch-making-and-usage.png" { return nil } + // Handwritten in the provider; do not copy from third_party (see getCompileFilesInFolder for .tmpl). + if di.Name() == "cloud_clients.go" { + return nil + } fname := strings.TrimPrefix(path, "third_party/terraform/") target := fname @@ -655,6 +659,10 @@ func (t Terraform) getCompileFilesInFolder(folderPath, targetDir string) map[str return err } if !di.IsDir() && strings.HasSuffix(di.Name(), ".tmpl") { + // Provider maintains google/transport/cloud_clients.go by hand while phasing out generated clients. + if di.Name() == "cloud_clients.go.tmpl" { + return nil + } fname := strings.TrimPrefix(path, "third_party/terraform/") fname = strings.TrimSuffix(fname, ".tmpl") target := fname diff --git a/mmv1/provider/terraform/common~compile.yaml b/mmv1/provider/terraform/common~compile.yaml index 266818c89957..391870676f33 100644 --- a/mmv1/provider/terraform/common~compile.yaml +++ b/mmv1/provider/terraform/common~compile.yaml @@ -85,6 +85,7 @@ <% Dir["third_party/terraform/transport/*.go.erb"].each do |file_path| fname = file_path.split('/')[-1] + next if fname == "cloud_clients.go.erb" -%> '<%= dir -%>/transport/<%= fname.delete_suffix(".erb") -%>': 'third_party/terraform/transport/<%= fname -%>' <% end -%> diff --git a/mmv1/provider/terraform/common~copy.yaml b/mmv1/provider/terraform/common~copy.yaml index 1784bffb4170..a6fc5e9c1e42 100644 --- a/mmv1/provider/terraform/common~copy.yaml +++ b/mmv1/provider/terraform/common~copy.yaml @@ -83,6 +83,7 @@ <% Dir["third_party/terraform/transport/*.go"].each do |file_path| fname = file_path.split('/')[-1] + next if fname == "cloud_clients.go" -%> '<%= dir -%>/transport/<%= fname -%>': 'third_party/terraform/transport/<%= fname -%>' <% end -%> diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index f7b750f690fa..480a731ef3e3 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -1,31 +1,42 @@ -{{/*# The license inside this block applies to this file. - # Copyright 2024 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. -*/}} +{{/* The license inside this block applies to this file + Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +{{$.CodeHeader TemplatePath}} package {{ lower $.ProductMetadata.Name }} import ( "context" + "errors" + "fmt" + "log" + "regexp" - // This shouldn't be from the cloud pkg but instead an internal package within magicmodules (e.g tpgresource/...) "github.com/hashicorp/terraform-plugin-framework/list" listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "google.golang.org/api/iterator" - "github.com/hashicorp/terraform-provider-google/google/tpgresource" + "{{ $.ImportPath }}/tpgresource" + transport_tpg "{{ $.ImportPath }}/transport" + + "google.golang.org/api/googleapi" ) var _ tpgresource.ListResourceWithRawV5Schemas = &{{ $.ResourceName -}}ListResource{} @@ -39,7 +50,7 @@ func New{{ $.ResourceName -}}ListResource() list.ListResource { } func (r *{{ $.ResourceName -}}ListResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = "google_{{ $.ProductMetadata.TerraformName -}}_{{ $.Name -}}" + resp.TypeName = "{{ $.TerraformName }}" } func (r *{{ $.ResourceName -}}ListResource) RawV5Schemas(ctx context.Context, _ list.RawV5SchemaRequest, resp *list.RawV5SchemaResponse) { @@ -55,61 +66,25 @@ func (r *{{ $.ResourceName -}}ListResource) Configure(_ context.Context, req res func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) { resp.Schema = listschema.Schema{ Attributes: map[string]listschema.Attribute{ - {{- range $identity := $.IdentityProperties }} // we can't rely on this because of some resources not containing all the possible parent combinations for list, we should rely more on `base_url` - "{{ $identity.Name }}": listschema.StringAttribute{ +{{- range $identity := $.IdentityProperties }} + "{{ underscore $identity.Name }}": listschema.StringAttribute{ Optional: true, }, - {{- end }}, - ~> we need logic to determine whether we can add filter support here or not - +{{- end }} "filter": listschema.StringAttribute{ Optional: true, }, - }, } } type {{ $.ResourceName -}}ListModel struct { - {{- range $identity := $.IdentityProperties }} - {{ $identity.Name }} string `tfsdk:"{{ $identity.Name }}"` - {{- end }} +{{- range $identity := $.IdentityProperties }} + {{ $identity.TitlelizeProperty }} types.String `tfsdk:"{{ underscore $identity.Name }}"` +{{- end }} + Filter types.String `tfsdk:"filter"` } -{{ if $.CustomListMethod }} - {{ $.CustomTemplate $.CustomListMethod false -}} -{{ else }} - func List{{ $.ResourceName -}}s(ctx context.Context, req list.ListRequest) { - client := r.Client.New{{ $.ResourceName -}}sClient(r.Client.UserAgent) - - listReq := {{lower $.ProductMetadata.Name }}.List{{ $.Name -}}sRequest{ - {{if $.NonParent }} - Parent: {{ $.ParentResourceName}}, - {{else}} - {{- range $identity := $.IdentityProperties }} - {{ $identity.Name }}: data.{{ $identity.Name }}, - {{- end }} - {{ if not (or $.ExcludeFilter $.CustomFilter) -}} - Filter: data.Filter - {{ end }} - {{ end }} - } - - it := client.List{{ $.Name -}}s(ctx, &listReq) - - for { - resp, err := it.Next() - if err == iterator.Done { - break - } else if err != nil { - diags.AddError("API Error", err.Error()) - break - } - - } - } -{{ end }} - func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { var data {{ $.ResourceName -}}ListModel diags := req.Config.Get(ctx, &data) @@ -118,49 +93,270 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L return } - /* INSERT IDENTITY SETTING GENERATION CODE HERE */ +{{- range $identity := $.IdentityProperties }} + var {{ $identity.CamelizeProperty }} string + if !data.{{ $identity.TitlelizeProperty }}.IsNull() && !data.{{ $identity.TitlelizeProperty }}.IsUnknown() { + {{ $identity.CamelizeProperty }} = data.{{ $identity.TitlelizeProperty }}.ValueString() + } +{{- if eq $identity.Name "project" }} + if {{ $identity.CamelizeProperty }} == "" { + {{ $identity.CamelizeProperty }} = r.Client.Project + } +{{- else if eq $identity.Name "zone" }} + if {{ $identity.CamelizeProperty }} == "" { + {{ $identity.CamelizeProperty }} = r.Client.Zone + } +{{- else if eq $identity.Name "region" }} + if {{ $identity.CamelizeProperty }} == "" { + {{ $identity.CamelizeProperty }} = r.Client.Region + } +{{- end }} +{{- end }} + filterString := "" + if !data.Filter.IsNull() && !data.Filter.IsUnknown() { + filterString = data.Filter.ValueString() + } stream.Results = func(push func(list.ListResult) bool) { + err := List{{ $.ResourceName }}s( + r.Client, + filterString, +{{- range $identity := $.IdentityProperties }} + {{ $identity.CamelizeProperty }}, +{{- end }} + func(rd *schema.ResourceData) error { +{{- $hasListName := false -}} +{{- range $identity := $.IdentityProperties }} +{{- if eq $identity.Name "name" }} +{{- $hasListName = true -}} +{{- end }} +{{- end }} +{{- if $hasListName }} + if name != "" { + if n, ok := rd.GetOk("name"); !ok || n.(string) != name { + return nil + } + } +{{- end }} + result := req.NewListResult(ctx) - LIST METHOD (func(){ - - result := req.NewListResult(ctx) - result.DisplayName = resp.Name - - {{ $.ResourceName -}}Resource := Resource{{ $.ResourceName -}}() - rd := {{ $.ResourceName -}}Resource.Data(&terraform.InstanceState{}) - rd.SetId(resp.Name) - - /* INSERT IDENTITY SETTING GENERATION CODE HERE */ + identity, err := rd.Identity() + if err != nil { + return fmt.Errorf("Error getting identity: %s", err) + } +{{- range $p := $.IdentityProperties }} +{{- if or (eq $p.Name "project") (eq $p.Name "zone") (eq $p.Name "region") (eq $p.Name "location") }} + if err = identity.Set("{{ underscore $p.Name }}", {{ $p.CamelizeProperty }}); err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name }}: %s", err) + } +{{- end }} +{{- end }} tfTypeIdentity, err := rd.TfTypeIdentityState() if err != nil { - diags.AddError("error getting identity state", err.Error()) - break + return err } if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil { - diags = err - break + return errors.New("error setting identity") } - tfTypeResource, err := rd.TfTypeResourceState() - if err != nil { - diags.AddError("error getting resource state", err.Error()) - break + if n, ok := rd.GetOk("name"); ok { + if s, ok := n.(string); ok { + result.DisplayName = s + } } - if err := result.Resource.Set(ctx, *tfTypeResource); err != nil { - diags = err - break + + if req.IncludeResource { + tfTypeResource, err := rd.TfTypeResourceState() + if err != nil { + return err + } + if err := result.Resource.Set(ctx, *tfTypeResource); err != nil { + return errors.New("error setting resource") + } } if !push(result) { - diags.AddError("stream closed", "stream closed") - break + return errors.New("stream closed") + } + return nil + }, + ) + if err != nil { + diags.AddError("API Error", err.Error()) + result := req.NewListResult(ctx) + result.Diagnostics = diags + push(result) + } + stream.Results = list.ListResultsStreamDiagnostics(diags) + } +} + +func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, +{{- range $identity := $.IdentityProperties }} + {{ $identity.CamelizeProperty }} string, +{{- end }} + callback func(*schema.ResourceData) error, +) error { + resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) +{{- range $identity := $.IdentityProperties }} + if {{ $identity.CamelizeProperty }} != "" { + if err := resourceData.Set("{{ underscore $identity.Name }}", {{ $identity.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $identity.Name }} on temporary resource data: %w", err) + } + } +{{- end }} + + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(resourceData, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.BaseUrl}}") + if err != nil { + return err + } + + billingProject := "" + if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { + billingProject = parts[1] + } + if bp, err := tpgresource.GetBillingProject(resourceData, config); err == nil { + billingProject = bp + } + + userAgent, err := tpgresource.GenerateUserAgentString(resourceData, config.UserAgent) + if err != nil { + return err + } + + return transport_tpg.ListPages( + config, + resourceData, + url, + billingProject, + userAgent, + "{{ $.ResourceListKey }}", + filter, + flatten{{ $.ResourceName }}ListItem, + callback, + ) +} + +func flatten{{ $.ResourceName }}ListItem(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { +{{- if $.NestedQuery }} + res, err := flattenNested{{ $.ResourceName }}(d, interface{}(config), res) + if err != nil { + return err + } + if res == nil { + return nil + } +{{- end }} +{{- if $.CustomCode.Decoder }} + {{- if $.NestedQuery }} + res, err = resource{{ $.ResourceName }}Decoder(d, interface{}(config), res) + {{- else }} + var err error + res, err = resource{{ $.ResourceName }}Decoder(d, interface{}(config), res) + {{- end }} + if err != nil { + return err + } + if res == nil { + return nil + } +{{- end }} +{{- if $.VirtualFields }} +{{- range $prop := $.VirtualFields }} +{{- if not (eq $prop.DefaultValue nil) }} + if _, ok := d.GetOkExists("{{ $prop.Name -}}"); !ok { + if err := d.Set("{{ $prop.Name -}}", {{ $prop.GoLiteral $prop.DefaultValue -}}); err != nil { + return fmt.Errorf("Error setting {{ $prop.Name -}}: %s", err) + } + } +{{- end }} +{{- end }} +{{- end }} +{{- if $.HasProject }} + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for {{ $.Name -}}: %s", err) + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } +{{- end }} +{{- if $.HasRegion }} + region, err := tpgresource.GetRegion(d, config) + if err != nil { + return err + } + if err := d.Set("region", region); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } +{{- end }} +{{- if $.HasZone }} + zone, err := tpgresource.GetZone(d, config) + if err != nil { + return err + } + if err := d.Set("zone", zone); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } +{{- end }} +{{- range $prop := $.GettableProperties }} +{{- if $prop.FlattenObject }} + if flattenedProp := flatten{{ if $.NestedQuery -}}Nested{{ end }}{{ $.ResourceName -}}{{ camelize $prop.Name "upper" -}}(res["{{ $prop.ApiName -}}"], d, config); flattenedProp != nil { + if gerr, ok := flattenedProp.(*googleapi.Error); ok { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", gerr) + } + casted := flattenedProp.([]interface{})[0] + if casted != nil { + for k, v := range casted.(map[string]interface{}) { + if err := d.Set(k, v); err != nil { + return fmt.Errorf("Error setting %s: %s", k, err) } } - - )} + } + } +{{- else }} + if err := d.Set("{{ underscore $prop.Name -}}", flatten{{ if $.NestedQuery -}}Nested{{ end }}{{ $.ResourceName -}}{{ camelize $prop.Name "upper" -}}(res["{{ $prop.ApiName -}}"], d, config)); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } +{{- end }} +{{- end }} +{{- if $.HasSelfLink }} + if err := d.Set("self_link", tpgresource.ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } +{{- end }} - stream.Results = list.ListResultsStreamDiagnostics(diags) + id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) } + d.SetId(id) + +{{- if and (not $.ExcludeIdentityGeneration) (not $.ExcludeRead) }} + identity, err := d.Identity() + if err == nil && identity != nil { +{{- range $p := $.IdentityProperties }} +{{- if eq $p.Type "Integer" }} + if _, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok { + err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(int)) + if err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + } + } +{{- else }} + if v, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok && v == "" { + err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string)) + if err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + } + } +{{- end }} +{{- end }} + } else { + log.Printf("[DEBUG] (list item) identity not set: %s", err) + } +{{- end }} + return nil +} diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index d89080007e3d..9e5f4edca5c0 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -36,11 +36,6 @@ import ( "time" "github.com/hashicorp/errwrap" - {{ if $.GenerateListResource -}} - "github.com/hashicorp/terraform-plugin-framework/list" - listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" - "github.com/hashicorp/terraform-plugin-framework/resource" - {{ end -}} "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" @@ -105,10 +100,6 @@ func init() { }.Register() } -{{- if $.GenerateListResource }} - {{- $.CustomTemplate "templates/terraform/list_resource.go.tmpl" false -}} -{{- end }} - func Resource{{ $.ResourceName -}}() *schema.Resource { return &schema.Resource{ Create: resource{{ $.ResourceName -}}Create, From bd659cf35f3842150fece94f651268c6c36bace9 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 9 Apr 2026 16:13:48 -0700 Subject: [PATCH 037/100] refactor to use flattenResource method generated from mau/flattenResource PR --- .../templates/terraform/list_resource.go.tmpl | 195 +++++++++--------- 1 file changed, 93 insertions(+), 102 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 480a731ef3e3..a601176e689a 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -24,7 +24,11 @@ import ( "errors" "fmt" "log" + "net/http" "regexp" +{{- if and $.HasProject $.LegacyLongFormProject }} + "strings" +{{- end }} "github.com/hashicorp/terraform-plugin-framework/list" listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" @@ -35,8 +39,6 @@ import ( "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" - - "google.golang.org/api/googleapi" ) var _ tpgresource.ListResourceWithRawV5Schemas = &{{ $.ResourceName -}}ListResource{} @@ -234,129 +236,118 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, userAgent, "{{ $.ResourceListKey }}", filter, - flatten{{ $.ResourceName }}ListItem, - callback, - ) -} - -func flatten{{ $.ResourceName }}ListItem(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { -{{- if $.NestedQuery }} - res, err := flattenNested{{ $.ResourceName }}(d, interface{}(config), res) - if err != nil { - return err - } - if res == nil { - return nil - } -{{- end }} -{{- if $.CustomCode.Decoder }} - {{- if $.NestedQuery }} - res, err = resource{{ $.ResourceName }}Decoder(d, interface{}(config), res) - {{- else }} - var err error - res, err = resource{{ $.ResourceName }}Decoder(d, interface{}(config), res) - {{- end }} - if err != nil { - return err - } - if res == nil { - return nil - } -{{- end }} + func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { +{{- if $.ExcludeRead }} + return fmt.Errorf("list resource for {{ $.Name }} requires read support (resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") +{{- else }} + meta := interface{}(config) {{- if $.VirtualFields }} + + // Explicitly set virtual fields to default values if unset (same order as resource{{ $.ResourceName }}Read) {{- range $prop := $.VirtualFields }} {{- if not (eq $prop.DefaultValue nil) }} - if _, ok := d.GetOkExists("{{ $prop.Name -}}"); !ok { - if err := d.Set("{{ $prop.Name -}}", {{ $prop.GoLiteral $prop.DefaultValue -}}); err != nil { - return fmt.Errorf("Error setting {{ $prop.Name -}}: %s", err) - } - } + if _, ok := d.GetOkExists("{{ $prop.Name -}}"); !ok { + if err := d.Set("{{ $prop.Name -}}", {{ $prop.GoLiteral $prop.DefaultValue -}}); err != nil { + return fmt.Errorf("Error setting {{ $prop.Name -}}: %s", err) + } + } {{- end }} {{- end }} {{- end }} {{- if $.HasProject }} - project, err := tpgresource.GetProject(d, config) - if err != nil { - return fmt.Errorf("Error fetching project for {{ $.Name -}}: %s", err) - } - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) - } + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for {{ $.Name -}}: %s", err) + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } {{- end }} {{- if $.HasRegion }} - region, err := tpgresource.GetRegion(d, config) - if err != nil { - return err - } - if err := d.Set("region", region); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) - } + region, err := tpgresource.GetRegion(d, config) + if err != nil { + return err + } + if err := d.Set("region", region); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } {{- end }} {{- if $.HasZone }} - zone, err := tpgresource.GetZone(d, config) - if err != nil { - return err - } - if err := d.Set("zone", zone); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) - } + zone, err := tpgresource.GetZone(d, config) + if err != nil { + return err + } + if err := d.Set("zone", zone); err != nil { + return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + } {{- end }} -{{- range $prop := $.GettableProperties }} -{{- if $prop.FlattenObject }} - if flattenedProp := flatten{{ if $.NestedQuery -}}Nested{{ end }}{{ $.ResourceName -}}{{ camelize $prop.Name "upper" -}}(res["{{ $prop.ApiName -}}"], d, config); flattenedProp != nil { - if gerr, ok := flattenedProp.(*googleapi.Error); ok { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", gerr) - } - casted := flattenedProp.([]interface{})[0] - if casted != nil { - for k, v := range casted.(map[string]interface{}) { - if err := d.Set(k, v); err != nil { - return fmt.Errorf("Error setting %s: %s", k, err) - } + + itemUserAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err } - } - } + + readURL, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") + if err != nil { + return err + } + + itemBillingProject := "" +{{- if $.HasProject }} +{{- if $.LegacyLongFormProject }} + itemBillingProject = strings.TrimPrefix(project, "projects/") {{- else }} - if err := d.Set("{{ underscore $prop.Name -}}", flatten{{ if $.NestedQuery -}}Nested{{ end }}{{ $.ResourceName -}}{{ camelize $prop.Name "upper" -}}(res["{{ $prop.ApiName -}}"], d, config)); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) - } + itemBillingProject = project {{- end }} {{- end }} -{{- if $.HasSelfLink }} - if err := d.Set("self_link", tpgresource.ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) - } +{{- if $.SupportsIndirectUserProjectOverride }} + if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(readURL); parts != nil { + itemBillingProject = parts[1] + } {{- end }} + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + itemBillingProject = bp + } - id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) + headers := make(http.Header) -{{- if and (not $.ExcludeIdentityGeneration) (not $.ExcludeRead) }} - identity, err := d.Identity() - if err == nil && identity != nil { -{{- range $p := $.IdentityProperties }} -{{- if eq $p.Type "Integer" }} - if _, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok { - err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(int)) - if err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + if err := resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}project,{{ end }} itemUserAgent, itemBillingProject, readURL, headers); err != nil { + return err } - } -{{- else }} - if v, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok && v == "" { - err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string)) + + id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") if err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + return fmt.Errorf("Error constructing id: %s", err) } - } + d.SetId(id) + +{{- if not $.ExcludeIdentityGeneration }} + identity, err := d.Identity() + if err == nil && identity != nil { +{{- range $p := $.IdentityProperties }} +{{- if eq $p.Type "Integer" }} + if _, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok { + err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(int)) + if err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + } + } +{{- else }} + if v, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok && v == "" { + err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string)) + if err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + } + } {{- end }} {{- end }} - } else { - log.Printf("[DEBUG] (list item) identity not set: %s", err) - } + } else { + log.Printf("[DEBUG] (list item) identity not set: %s", err) + } +{{- end }} + return nil {{- end }} - return nil + }, + callback, + ) } From e8e8ae8e16c74a8b4a6aa98b4274bf41bdb2b2fb Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 13:01:05 -0700 Subject: [PATCH 038/100] major refactoring --- mmv1/api/resource.go | 9 +- mmv1/provider/terraform.go | 3 + .../templates/terraform/list_resource.go.tmpl | 108 +++++++++++------- .../terraform/tpgresource/list_resource.go | 12 ++ 4 files changed, 92 insertions(+), 40 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 1acf71397cdd..f7272e89f5f6 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -251,7 +251,7 @@ type Resource struct { // If true, skip sweeper generation for this resource ExcludeSweeper bool `yaml:"exclude_sweeper,omitempty"` - // If true, skip identity generation for this resource + // If true, skip identity generation for this resource. Incompatible with generate_list_resource. ExcludeIdentityGeneration bool `yaml:"exclude_identity_generation,omitempty"` // Override sweeper settings @@ -1317,6 +1317,13 @@ func (r Resource) HasZone() bool { return found && strings.Contains(r.BaseUrl, "{{zone}}") } +// HasLocation is true when URLs use a {{location}} segment (e.g. Cloud Run, Cloud Functions). +func (r Resource) HasLocation() bool { + return strings.Contains(r.BaseUrl, "{{location}}") || + strings.Contains(r.CreateUrl, "{{location}}") || + strings.Contains(r.SelfLinkUri(), "{{location}}") +} + // resource functions needed for template that previously existed in terraform.go // but due to how files are being inherited here it was easier to put in here // taken wholesale from tpgtools diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 3e25fb5ff0ce..c98c96e01a83 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -156,6 +156,9 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD templateData.GenerateResourceFile(targetFilePath, object) } if object.GenerateListResource { + if object.ExcludeIdentityGeneration { + log.Fatalf("generate_list_resource requires identity support; remove exclude_identity_generation from resource %q or disable generate_list_resource", object.Name) + } targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_resource_%s.go", t.ResourceGoFilename(object))) templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, "templates/terraform/list_resource.go.tmpl") } diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index a601176e689a..81e173081296 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -96,22 +96,19 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L } {{- range $identity := $.IdentityProperties }} +{{- if eq $identity.Name "project" }} + {{ $identity.CamelizeProperty }} := r.GetProject(data.{{ $identity.TitlelizeProperty }}) +{{- else if eq $identity.Name "region" }} + {{ $identity.CamelizeProperty }} := r.GetRegion(data.{{ $identity.TitlelizeProperty }}) +{{- else if eq $identity.Name "zone" }} + {{ $identity.CamelizeProperty }} := r.GetZone(data.{{ $identity.TitlelizeProperty }}) +{{- else if eq $identity.Name "location" }} + {{ $identity.CamelizeProperty }} := r.GetLocation(data.{{ $identity.TitlelizeProperty }}) +{{- else }} var {{ $identity.CamelizeProperty }} string if !data.{{ $identity.TitlelizeProperty }}.IsNull() && !data.{{ $identity.TitlelizeProperty }}.IsUnknown() { {{ $identity.CamelizeProperty }} = data.{{ $identity.TitlelizeProperty }}.ValueString() } -{{- if eq $identity.Name "project" }} - if {{ $identity.CamelizeProperty }} == "" { - {{ $identity.CamelizeProperty }} = r.Client.Project - } -{{- else if eq $identity.Name "zone" }} - if {{ $identity.CamelizeProperty }} == "" { - {{ $identity.CamelizeProperty }} = r.Client.Zone - } -{{- else if eq $identity.Name "region" }} - if {{ $identity.CamelizeProperty }} == "" { - {{ $identity.CamelizeProperty }} = r.Client.Region - } {{- end }} {{- end }} @@ -143,25 +140,15 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L {{- end }} result := req.NewListResult(ctx) - identity, err := rd.Identity() - if err != nil { - return fmt.Errorf("Error getting identity: %s", err) - } + if err := tpgresource.SetIdentityFields(ctx, &result, rd, map[string]string{ {{- range $p := $.IdentityProperties }} {{- if or (eq $p.Name "project") (eq $p.Name "zone") (eq $p.Name "region") (eq $p.Name "location") }} - if err = identity.Set("{{ underscore $p.Name }}", {{ $p.CamelizeProperty }}); err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name }}: %s", err) - } + "{{ underscore $p.Name }}": {{ $p.CamelizeProperty }}, {{- end }} {{- end }} - - tfTypeIdentity, err := rd.TfTypeIdentityState() - if err != nil { + }); err != nil { return err } - if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil { - return errors.New("error setting identity") - } if n, ok := rd.GetOk("name"); ok { if s, ok := n.(string); ok { @@ -202,12 +189,17 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, callback func(*schema.ResourceData) error, ) error { resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) +{{- $listUrlIds := $.ExtractIdentifiers $.BaseUrl }} {{- range $identity := $.IdentityProperties }} +{{- range $id := $listUrlIds }} +{{- if eq $id (underscore $identity.Name) }} if {{ $identity.CamelizeProperty }} != "" { if err := resourceData.Set("{{ underscore $identity.Name }}", {{ $identity.CamelizeProperty }}); err != nil { return fmt.Errorf("error setting {{ underscore $identity.Name }} on temporary resource data: %w", err) } } +{{- end }} +{{- end }} {{- end }} url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(resourceData, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.BaseUrl}}") @@ -254,31 +246,71 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, {{- end }} {{- end }} {{- end }} +{{- /* List scope (project/region/zone/location) is constant for the whole list call; re-apply from ListXxxs args so ReplaceVars sees correct values after Flatten mutates shared d. */ -}} +{{- $liProject := false -}} +{{- $liRegion := false -}} +{{- $liZone := false -}} +{{- $liLocation := false -}} +{{- range $identity := $.IdentityProperties }} +{{- if eq $identity.Name "project" }}{{- $liProject = true -}}{{- end }} +{{- if eq $identity.Name "region" }}{{- $liRegion = true -}}{{- end }} +{{- if eq $identity.Name "zone" }}{{- $liZone = true -}}{{- end }} +{{- if eq $identity.Name "location" }}{{- $liLocation = true -}}{{- end }} +{{- end }} {{- if $.HasProject }} - project, err := tpgresource.GetProject(d, config) - if err != nil { - return fmt.Errorf("Error fetching project for {{ $.Name -}}: %s", err) + var itemProject string +{{- if $liProject }} + itemProject = project + if itemProject != "" { + if err := d.Set("project", itemProject); err != nil { + return fmt.Errorf("error setting project on list item temporary resource data: %w", err) + } + } +{{- else }} + var errProj error + itemProject, errProj = tpgresource.GetProject(d, config) + if errProj != nil { + return fmt.Errorf("error fetching project for {{ $.Name }}: %w", errProj) } - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + if err := d.Set("project", itemProject); err != nil { + return fmt.Errorf("error setting project on list item temporary resource data: %w", err) } {{- end }} -{{- if $.HasRegion }} +{{- end }} +{{- range $identity := $.IdentityProperties }} +{{- if or (eq $identity.Name "region") (eq $identity.Name "zone") (eq $identity.Name "location") }} + if {{ $identity.CamelizeProperty }} != "" { + if err := d.Set("{{ underscore $identity.Name }}", {{ $identity.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $identity.Name }} on list item temporary resource data: %w", err) + } + } +{{- end }} +{{- end }} +{{- if and $.HasRegion (not $liRegion) }} region, err := tpgresource.GetRegion(d, config) if err != nil { return err } if err := d.Set("region", region); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + return fmt.Errorf("error setting region on list item temporary resource data: %w", err) } {{- end }} -{{- if $.HasZone }} +{{- if and $.HasZone (not $liZone) }} zone, err := tpgresource.GetZone(d, config) if err != nil { return err } if err := d.Set("zone", zone); err != nil { - return fmt.Errorf("Error reading {{ $.Name -}}: %s", err) + return fmt.Errorf("error setting zone on list item temporary resource data: %w", err) + } +{{- end }} +{{- if and $.HasLocation (not $liLocation) }} + location, err := tpgresource.GetLocation(d, config) + if err != nil { + return err + } + if err := d.Set("location", location); err != nil { + return fmt.Errorf("error setting location on list item temporary resource data: %w", err) } {{- end }} @@ -295,9 +327,9 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, itemBillingProject := "" {{- if $.HasProject }} {{- if $.LegacyLongFormProject }} - itemBillingProject = strings.TrimPrefix(project, "projects/") + itemBillingProject = strings.TrimPrefix(itemProject, "projects/") {{- else }} - itemBillingProject = project + itemBillingProject = itemProject {{- end }} {{- end }} {{- if $.SupportsIndirectUserProjectOverride }} @@ -311,7 +343,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, headers := make(http.Header) - if err := resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}project,{{ end }} itemUserAgent, itemBillingProject, readURL, headers); err != nil { + if err := resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}itemProject,{{ end }} itemUserAgent, itemBillingProject, readURL, headers); err != nil { return err } @@ -321,7 +353,6 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, } d.SetId(id) -{{- if not $.ExcludeIdentityGeneration }} identity, err := d.Identity() if err == nil && identity != nil { {{- range $p := $.IdentityProperties }} @@ -344,7 +375,6 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, } else { log.Printf("[DEBUG] (list item) identity not set: %s", err) } -{{- end }} return nil {{- end }} }, diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index f80dc23d62d8..a70dc2db0dee 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -282,6 +282,18 @@ func (r *ListResourceMetadata) GetZone(override types.String) string { return r.Zone } +// GetLocation returns the location from the list block override if set and non-empty, +// otherwise falls back to the provider-level region (typical default for regional APIs). +// Used by MM-generated list resources together with GetProject/GetRegion/GetZone + SetIdentityFields above. +func (r *ListResourceMetadata) GetLocation(override types.String) string { + if !override.IsNull() && !override.IsUnknown() { + if v := override.ValueString(); v != "" { + return v + } + } + return r.Region +} + func SetIdentityFields(ctx context.Context, result *list.ListResult, rd *schema.ResourceData, fields map[string]string) error { identity, err := rd.Identity() if err != nil { From 686b598b1acab41eb8f73daeab9f754c486d810a Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 13:25:44 -0700 Subject: [PATCH 039/100] remove cloud_clients.go.tmpl --- .../terraform/transport/cloud_clients.go.tmpl | 166 ------------------ 1 file changed, 166 deletions(-) delete mode 100644 mmv1/third_party/terraform/transport/cloud_clients.go.tmpl diff --git a/mmv1/third_party/terraform/transport/cloud_clients.go.tmpl b/mmv1/third_party/terraform/transport/cloud_clients.go.tmpl deleted file mode 100644 index 03b70c9cf2d5..000000000000 --- a/mmv1/third_party/terraform/transport/cloud_clients.go.tmpl +++ /dev/null @@ -1,166 +0,0 @@ -package transport - -import ( - "log" - - // cloud.google.com/go packages - All available Google Cloud products - // Reference: https://docs.cloud.google.com/go/docs/reference - // Only packages listed in the official documentation are included - - // Access & Security - accessapproval "cloud.google.com/go/accessapproval/apiv1" - accesscontextmanager "cloud.google.com/go/accesscontextmanager/apiv1" - binaryauthorization "cloud.google.com/go/binaryauthorization/apiv1" - iam "cloud.google.com/go/iam" - iamcredentials "cloud.google.com/go/iam/credentials/apiv1" - iap "cloud.google.com/go/iap/apiv1" - orgpolicy "cloud.google.com/go/orgpolicy/apiv2" - recaptchaenterprise "cloud.google.com/go/recaptchaenterprise/v2/apiv1" - securitycenter "cloud.google.com/go/securitycenter/apiv1" - securitycentermanagement "cloud.google.com/go/securitycentermanagement/apiv1" - - // AI & Machine Learning - aiplatform "cloud.google.com/go/aiplatform/apiv1" - automl "cloud.google.com/go/automl/apiv1" - documentai "cloud.google.com/go/documentai/apiv1" - language "cloud.google.com/go/language/apiv1" - languagev2 "cloud.google.com/go/language/apiv2" - speech "cloud.google.com/go/speech/apiv1" - speechv2 "cloud.google.com/go/speech/apiv2" - texttospeech "cloud.google.com/go/texttospeech/apiv1" - translate "cloud.google.com/go/translate/apiv3" - videointelligence "cloud.google.com/go/videointelligence/apiv1" - vision "cloud.google.com/go/vision/apiv1" - visionv2 "cloud.google.com/go/vision/v2/apiv1" - - // Analytics & Data - bigquery "cloud.google.com/go/bigquery" - datacatalog "cloud.google.com/go/datacatalog/apiv1" - dataplex "cloud.google.com/go/dataplex/apiv1" - datastore "cloud.google.com/go/datastore" - - // Application Development - appengine "cloud.google.com/go/appengine/apiv1" - cloudbuild "cloud.google.com/go/cloudbuild/apiv1" - cloudrun "cloud.google.com/go/run/apiv2" - scheduler "cloud.google.com/go/scheduler/apiv1" - - // Compute & Infrastructure - baremetalsolution "cloud.google.com/go/baremetalsolution/apiv2" - compute "cloud.google.com/go/compute/apiv1" - container "cloud.google.com/go/container/apiv1" - edgecontainer "cloud.google.com/go/edgecontainer/apiv1" - edgenetwork "cloud.google.com/go/edgenetwork/apiv1" - filestore "cloud.google.com/go/filestore/apiv1" - tpu "cloud.google.com/go/tpu/apiv1" - vmmigration "cloud.google.com/go/vmmigration/apiv1" - vmwareengine "cloud.google.com/go/vmwareengine/apiv1" - vpcaccess "cloud.google.com/go/vpcaccess/apiv1" - - // Databases - alloydb "cloud.google.com/go/alloydb/apiv1" - bigtable "cloud.google.com/go/bigtable" - datastream "cloud.google.com/go/datastream/apiv1" - firestore "cloud.google.com/go/firestore" - memcache "cloud.google.com/go/memcache/apiv1" - metastore "cloud.google.com/go/metastore/apiv1" - metastorealpha "cloud.google.com/go/metastore/apiv1alpha" - metastorebeta "cloud.google.com/go/metastore/apiv1beta" - redis "cloud.google.com/go/redis/apiv1" - spanner "cloud.google.com/go/spanner" - - // Developer Tools - artifactregistry "cloud.google.com/go/artifactregistry/apiv1" - clouddms "cloud.google.com/go/clouddms/apiv1" - cloudquotas "cloud.google.com/go/cloudquotas/apiv1" - deploy "cloud.google.com/go/deploy/apiv1" - gsuiteaddons "cloud.google.com/go/gsuiteaddons/apiv1" - orchestration "cloud.google.com/go/orchestration/airflow/service/apiv1" - servicemanagement "cloud.google.com/go/servicemanagement/apiv1" - serviceusage "cloud.google.com/go/serviceusage/apiv1" - - // Identity & Directory - managedidentities "cloud.google.com/go/managedidentities/apiv1" - oslogin "cloud.google.com/go/oslogin/apiv1" - - // Management & Operations - asset "cloud.google.com/go/asset/apiv1" - billing "cloud.google.com/go/billing/apiv1" - cloudcontrolspartner "cloud.google.com/go/cloudcontrolspartner/apiv1" - essentialcontacts "cloud.google.com/go/essentialcontacts/apiv1" - logging "cloud.google.com/go/logging/apiv2" - osconfig "cloud.google.com/go/osconfig/apiv1" - policysimulator "cloud.google.com/go/policysimulator/apiv1" - policytroubleshooter "cloud.google.com/go/policytroubleshooter/apiv1" - recommender "cloud.google.com/go/recommender/apiv1" - resourcesettings "cloud.google.com/go/resourcesettings/apiv1" - servicedirectory "cloud.google.com/go/servicedirectory/apiv1" - trace "cloud.google.com/go/trace/apiv2" - - // Networking - networkconnectivity "cloud.google.com/go/networkconnectivity/apiv1" - networkmanagement "cloud.google.com/go/networkmanagement/apiv1" - networkservices "cloud.google.com/go/networkservices/apiv1" - - // Storage & Transfer - storage "cloud.google.com/go/storage" - storagetransfer "cloud.google.com/go/storagetransfer/apiv1" - - // Data Processing - batch "cloud.google.com/go/batch/apiv1" - dataflow "cloud.google.com/go/dataflow/apiv1beta3" - dataform "cloud.google.com/go/dataform/apiv1beta1" - datafusion "cloud.google.com/go/datafusion/apiv1" - lifesciences "cloud.google.com/go/lifesciences/apiv2beta" - workflows "cloud.google.com/go/workflows/apiv1" - - // Media & Content - videostitcher "cloud.google.com/go/video/stitcher/apiv1" - mediatranslation "cloud.google.com/go/mediatranslation/apiv1beta1" - - // Other Services - apigeeregistry "cloud.google.com/go/apigeeregistry/apiv1" - apikeys "cloud.google.com/go/apikeys/apiv2" - assuredworkloads "cloud.google.com/go/assuredworkloads/apiv1" - certificatemanager "cloud.google.com/go/certificatemanager/apiv1" - channel "cloud.google.com/go/channel/apiv1" - cloudtasks "cloud.google.com/go/cloudtasks/apiv2" - contactcenterinsights "cloud.google.com/go/contactcenterinsights/apiv1" - containeranalysis "cloud.google.com/go/containeranalysis/apiv1" - dlp "cloud.google.com/go/dlp/apiv2" - eventarc "cloud.google.com/go/eventarc/apiv1" - gaming "cloud.google.com/go/gaming/apiv1" - gkebackup "cloud.google.com/go/gkebackup/apiv1" - gkemulticloud "cloud.google.com/go/gkemulticloud/apiv1" - ids "cloud.google.com/go/ids/apiv1" - iot "cloud.google.com/go/iot/apiv1" - kms "cloud.google.com/go/kms/apiv1" - notebooks "cloud.google.com/go/notebooks/apiv1" - optimization "cloud.google.com/go/optimization/apiv1" - parallelstore "cloud.google.com/go/parallelstore/apiv1beta" - phishingprotection "cloud.google.com/go/phishingprotection/apiv1beta1" - privatecatalog "cloud.google.com/go/privatecatalog/apiv1beta1" - pubsub "cloud.google.com/go/pubsub" - secretmanager "cloud.google.com/go/secretmanager/apiv1" - talent "cloud.google.com/go/talent/apiv4" - webrisk "cloud.google.com/go/webrisk/apiv1" - websecurityscanner "cloud.google.com/go/websecurityscanner/apiv1" - workstations "cloud.google.com/go/workstations/apiv1" - - // Legacy google.golang.org/api packages (for compatibility) - "google.golang.org/api/option" -) - -{{ range $product := $.Products }} -{{ range $resource := $product.Objects }} -func (c *Config) New{{ $product.Name }}{{ $resource.Name }}sClient() *{{underscore $product.ApiName}}.{{ $resource.Name }}Client { - log.Printf("[INFO] Instantiating {{ $product.Name }}{{ $resource.Name }} client") - client{{ $product.Name }}{{ $resource.Name }}, err := {{$product.ApiName}}.{{ $product.Name }}{{ $resource.Name }}sClient(c.Context, option.WithHTTPClient(c.Client)) - if err != nil { - log.Printf("[WARN] Error creating {{ $product.Name }}{{ $resource.Name }} client: %s", err) - return nil - } - return client{{ $product.Name }}{{ $resource.Name }} -} -{{ end }} -{{ end }} \ No newline at end of file From 34bd38722a086cedb589f65a1f4f38f250239c61 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 13:40:46 -0700 Subject: [PATCH 040/100] include gneerated list resources in framework_mmv1 --- mmv1/provider/terraform.go | 56 +++++++++++++++++++ .../framework_provider_mmv1_resources.go.tmpl | 26 +++++++++ 2 files changed, 82 insertions(+) create mode 100644 mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index c98c96e01a83..e7ea8d66d670 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -1065,3 +1065,59 @@ type ProviderWithProducts struct { Compiler string Products []*api.Product } + +// GeneratedListResourceRegistration describes one MMv1-generated list resource constructor +// for framework_provider_mmv1_resources.go.tmpl. +type GeneratedListResourceRegistration struct { + Package string // Go service package name (product ApiName), e.g. "cloudrun" + NewFunc string // e.g. "NewCloudRunServiceListResource" +} + +// GetGeneratedListResourcesInVersion returns list-resource registrations for all products +// in the same order as list_resource_*.go generation (version, exclude, generate_list_resource). +func (t Terraform) GetGeneratedListResourcesInVersion(products []*api.Product) []GeneratedListResourceRegistration { + var out []GeneratedListResourceRegistration + for _, productDefinition := range products { + for _, object := range productDefinition.Objects { + if object.Exclude || object.NotInVersion(productDefinition.VersionObjOrClosest(t.TargetVersionName)) { + continue + } + if object.IsExcluded() { + continue + } + if !object.GenerateListResource { + continue + } + if object.ExcludeIdentityGeneration { + continue + } + out = append(out, GeneratedListResourceRegistration{ + Package: productDefinition.ApiName, + NewFunc: fmt.Sprintf("New%sListResource", object.ResourceName()), + }) + } + } + slices.SortFunc(out, func(a, b GeneratedListResourceRegistration) int { + if c := strings.Compare(a.Package, b.Package); c != 0 { + return c + } + return strings.Compare(a.NewFunc, b.NewFunc) + }) + return out +} + +// GetListResourceImportPackages returns sorted unique service import paths for generated list resources. +func (t Terraform) GetListResourceImportPackages(products []*api.Product) []string { + reg := t.GetGeneratedListResourcesInVersion(products) + seen := make(map[string]struct{}, len(reg)) + var pkgs []string + for _, r := range reg { + if _, ok := seen[r.Package]; ok { + continue + } + seen[r.Package] = struct{}{} + pkgs = append(pkgs, r.Package) + } + slices.Sort(pkgs) + return pkgs +} diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl new file mode 100644 index 000000000000..ba2eb00d313f --- /dev/null +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl @@ -0,0 +1,26 @@ +package fwprovider + +import ( + "github.com/hashicorp/terraform-plugin-framework/list" + + "github.com/hashicorp/terraform-provider-google/google/services/resourcemanager" +{{- $listPkgs := $.GetListResourceImportPackages $.Products }} +{{- range $pkg := $listPkgs }} + "github.com/hashicorp/terraform-provider-google/google/services/{{ $pkg }}" +{{- end }} +) + +func listResourceFunc(lr list.ListResource) func() list.ListResource { + return func() list.ListResource { return lr } +} + +// generatedListResources registers MMv1-generated list resources (generate_list_resource in YAML). +var generatedListResources = []func() list.ListResource{ +{{- range $lr := $.GetGeneratedListResourcesInVersion $.Products }} + listResourceFunc({{ $lr.Package }}.{{ $lr.NewFunc }}()), +{{- end }} +} + +var handwrittenListResources = []func() list.ListResource{ + listResourceFunc(resourcemanager.NewGoogleServiceAccountListResource()), +} From 27fe65e2efc06070c51d8ff43120622f4fd10254 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 13:52:02 -0700 Subject: [PATCH 041/100] first successful run of tf query on generated list resource (cloud_run_service) --- mmv1/templates/terraform/list_resource.go.tmpl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 81e173081296..1da29fb96518 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -189,17 +189,15 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, callback func(*schema.ResourceData) error, ) error { resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) -{{- $listUrlIds := $.ExtractIdentifiers $.BaseUrl }} + // ReplaceVars expands {{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}} (product default_base_url) and base_url using resourceData. + // base_url often omits vars that still appear in the base path (e.g. {{"{{"}}location{{"}}"}} in the host, {{"{{"}}project{{"}}"}} only in the path). + // Set every resolved list identity on resourceData before building the list URL. {{- range $identity := $.IdentityProperties }} -{{- range $id := $listUrlIds }} -{{- if eq $id (underscore $identity.Name) }} if {{ $identity.CamelizeProperty }} != "" { if err := resourceData.Set("{{ underscore $identity.Name }}", {{ $identity.CamelizeProperty }}); err != nil { return fmt.Errorf("error setting {{ underscore $identity.Name }} on temporary resource data: %w", err) } } -{{- end }} -{{- end }} {{- end }} url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(resourceData, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.BaseUrl}}") From ef852e8fc1fac051c4b73578d24ea6780b5e88e0 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 13:59:55 -0700 Subject: [PATCH 042/100] fix name being empty in list query results --- mmv1/templates/terraform/list_resource.go.tmpl | 10 ++++------ mmv1/templates/terraform/resource.go.tmpl | 14 ++++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 1da29fb96518..396b42fec456 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -355,16 +355,14 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, if err == nil && identity != nil { {{- range $p := $.IdentityProperties }} {{- if eq $p.Type "Integer" }} - if _, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok { - err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(int)) - if err != nil { + if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { + if err := identity.Set("{{ underscore $p.Name}}", v.(int)); err != nil { return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) } } {{- else }} - if v, ok := identity.GetOk("{{ underscore $p.Name}}"); !ok && v == "" { - err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string)) - if err != nil { + if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { + if err := identity.Set("{{ underscore $p.Name}}", v.(string)); err != nil { return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) } } diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index 9e5f4edca5c0..98694c2ad7e6 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -827,18 +827,16 @@ func resource{{ $.ResourceName -}}Read(d *schema.ResourceData, meta interface{}) if err == nil && identity != nil { {{- range $p := $.IdentityProperties }} {{ if eq $p.Type "Integer" -}} - if _, ok := identity.GetOk("{{ underscore $p.Name}}");!ok { - err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(int)) - if err != nil { + if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { + if err := identity.Set("{{ underscore $p.Name}}", v.(int)); err != nil { return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) } } {{- else -}} - if v, ok := identity.GetOk("{{ underscore $p.Name}}");!ok && v == "" { - err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string)) - if err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) - } + if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { + if err := identity.Set("{{ underscore $p.Name}}", v.(string)); err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + } } {{- end -}} {{- end }} From 8eb84a6e1446132e48f1934b3c58197d7491a4b3 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 14:35:00 -0700 Subject: [PATCH 043/100] refactor to handle setResult + setIdentity in list_resource metadata - more generic implementation --- .../templates/terraform/list_resource.go.tmpl | 50 ++++--------------- 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 396b42fec456..251bf404ee86 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -23,7 +23,6 @@ import ( "context" "errors" "fmt" - "log" "net/http" "regexp" {{- if and $.HasProject $.LegacyLongFormProject }} @@ -48,7 +47,13 @@ type {{ $.ResourceName -}}ListResource struct { } func New{{ $.ResourceName -}}ListResource() list.ListResource { - return &{{ $.ResourceName -}}ListResource{} + r := &{{ $.ResourceName -}}ListResource{} + r.IdentityAttributes = []string{ +{{- range $identity := $.IdentityProperties }} + "{{ underscore $identity.Name }}", +{{- end }} + } + return r } func (r *{{ $.ResourceName -}}ListResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) { @@ -140,30 +145,14 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L {{- end }} result := req.NewListResult(ctx) - if err := tpgresource.SetIdentityFields(ctx, &result, rd, map[string]string{ -{{- range $p := $.IdentityProperties }} -{{- if or (eq $p.Name "project") (eq $p.Name "zone") (eq $p.Name "region") (eq $p.Name "location") }} - "{{ underscore $p.Name }}": {{ $p.CamelizeProperty }}, -{{- end }} -{{- end }} - }); err != nil { - return err - } - if n, ok := rd.GetOk("name"); ok { if s, ok := n.(string); ok { result.DisplayName = s } } - if req.IncludeResource { - tfTypeResource, err := rd.TfTypeResourceState() - if err != nil { - return err - } - if err := result.Resource.Set(ctx, *tfTypeResource); err != nil { - return errors.New("error setting resource") - } + if err := r.SetResult(ctx, req.IncludeResource, &result, rd); err != nil { + return err } if !push(result) { @@ -350,27 +339,6 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - - identity, err := d.Identity() - if err == nil && identity != nil { -{{- range $p := $.IdentityProperties }} -{{- if eq $p.Type "Integer" }} - if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { - if err := identity.Set("{{ underscore $p.Name}}", v.(int)); err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) - } - } -{{- else }} - if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { - if err := identity.Set("{{ underscore $p.Name}}", v.(string)); err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) - } - } -{{- end }} -{{- end }} - } else { - log.Printf("[DEBUG] (list item) identity not set: %s", err) - } return nil {{- end }} }, From 341458678f9b5cd6efa0f5a55341cfef9c3b64fa Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 14:57:03 -0700 Subject: [PATCH 044/100] refactor to handle Configure / Metadata / RawV5Schemas in in list_resource metadata - more generic implementation --- .../templates/terraform/list_resource.go.tmpl | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 251bf404ee86..41c61adbb5a8 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -23,7 +23,7 @@ import ( "context" "errors" "fmt" - "net/http" +"net/http" "regexp" {{- if and $.HasProject $.LegacyLongFormProject }} "strings" @@ -31,7 +31,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/list" listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" - "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -48,6 +47,8 @@ type {{ $.ResourceName -}}ListResource struct { func New{{ $.ResourceName -}}ListResource() list.ListResource { r := &{{ $.ResourceName -}}ListResource{} + r.TypeName = "{{ $.TerraformName }}" + r.ResourceSchema = Resource{{ $.ResourceName -}}() r.IdentityAttributes = []string{ {{- range $identity := $.IdentityProperties }} "{{ underscore $identity.Name }}", @@ -56,20 +57,6 @@ func New{{ $.ResourceName -}}ListResource() list.ListResource { return r } -func (r *{{ $.ResourceName -}}ListResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = "{{ $.TerraformName }}" -} - -func (r *{{ $.ResourceName -}}ListResource) RawV5Schemas(ctx context.Context, _ list.RawV5SchemaRequest, resp *list.RawV5SchemaResponse) { - {{ $.ResourceName -}} := Resource{{ $.ResourceName -}}() - resp.ProtoV5Schema = {{ $.ResourceName -}}.ProtoSchema(ctx)() - resp.ProtoV5IdentitySchema = {{ $.ResourceName -}}.ProtoIdentitySchema(ctx)() -} - -func (r *{{ $.ResourceName -}}ListResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { - r.Defaults(req, resp) -} - func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) { resp.Schema = listschema.Schema{ Attributes: map[string]listschema.Attribute{ From de3404d1cdcaf99d734ffde185b194978f34db09 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 15:00:06 -0700 Subject: [PATCH 045/100] add ListScopeProperties for values from base_url string --- mmv1/api/resource.go | 17 ++++ .../templates/terraform/list_resource.go.tmpl | 90 ++++++++----------- 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index f7272e89f5f6..e572ae48acb8 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -718,6 +718,23 @@ func (r Resource) IdentityProperties() []*Type { return props } +// ListScopeProperties returns the subset of IdentityProperties whose +// template variable (e.g. {{project}}) appears in the full collection URL +// (product base_url + resource base_url). These are the scoping parameters +// a practitioner must supply for a list call — not the resource's own +// identifier like "name". +func (r Resource) ListScopeProperties() []*Type { + collectionUrl := r.CollectionUrl() + var props []*Type + for _, p := range r.IdentityProperties() { + varName := "{{" + google.Underscore(p.Name) + "}}" + if strings.Contains(collectionUrl, varName) { + props = append(props, p) + } + } + return props +} + func (r Resource) SensitiveProps() []*Type { props := r.AllNestedProperties(r.RootProperties()) return google.Select(props, func(p *Type) bool { diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 41c61adbb5a8..826164fd4ea0 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -23,7 +23,7 @@ import ( "context" "errors" "fmt" -"net/http" + "net/http" "regexp" {{- if and $.HasProject $.LegacyLongFormProject }} "strings" @@ -60,8 +60,8 @@ func New{{ $.ResourceName -}}ListResource() list.ListResource { func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) { resp.Schema = listschema.Schema{ Attributes: map[string]listschema.Attribute{ -{{- range $identity := $.IdentityProperties }} - "{{ underscore $identity.Name }}": listschema.StringAttribute{ +{{- range $scope := $.ListScopeProperties }} + "{{ underscore $scope.Name }}": listschema.StringAttribute{ Optional: true, }, {{- end }} @@ -73,8 +73,8 @@ func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context } type {{ $.ResourceName -}}ListModel struct { -{{- range $identity := $.IdentityProperties }} - {{ $identity.TitlelizeProperty }} types.String `tfsdk:"{{ underscore $identity.Name }}"` +{{- range $scope := $.ListScopeProperties }} + {{ $scope.TitlelizeProperty }} types.String `tfsdk:"{{ underscore $scope.Name }}"` {{- end }} Filter types.String `tfsdk:"filter"` } @@ -87,19 +87,19 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L return } -{{- range $identity := $.IdentityProperties }} -{{- if eq $identity.Name "project" }} - {{ $identity.CamelizeProperty }} := r.GetProject(data.{{ $identity.TitlelizeProperty }}) -{{- else if eq $identity.Name "region" }} - {{ $identity.CamelizeProperty }} := r.GetRegion(data.{{ $identity.TitlelizeProperty }}) -{{- else if eq $identity.Name "zone" }} - {{ $identity.CamelizeProperty }} := r.GetZone(data.{{ $identity.TitlelizeProperty }}) -{{- else if eq $identity.Name "location" }} - {{ $identity.CamelizeProperty }} := r.GetLocation(data.{{ $identity.TitlelizeProperty }}) +{{- range $scope := $.ListScopeProperties }} +{{- if eq $scope.Name "project" }} + {{ $scope.CamelizeProperty }} := r.GetProject(data.{{ $scope.TitlelizeProperty }}) +{{- else if eq $scope.Name "region" }} + {{ $scope.CamelizeProperty }} := r.GetRegion(data.{{ $scope.TitlelizeProperty }}) +{{- else if eq $scope.Name "zone" }} + {{ $scope.CamelizeProperty }} := r.GetZone(data.{{ $scope.TitlelizeProperty }}) +{{- else if eq $scope.Name "location" }} + {{ $scope.CamelizeProperty }} := r.GetLocation(data.{{ $scope.TitlelizeProperty }}) {{- else }} - var {{ $identity.CamelizeProperty }} string - if !data.{{ $identity.TitlelizeProperty }}.IsNull() && !data.{{ $identity.TitlelizeProperty }}.IsUnknown() { - {{ $identity.CamelizeProperty }} = data.{{ $identity.TitlelizeProperty }}.ValueString() + var {{ $scope.CamelizeProperty }} string + if !data.{{ $scope.TitlelizeProperty }}.IsNull() && !data.{{ $scope.TitlelizeProperty }}.IsUnknown() { + {{ $scope.CamelizeProperty }} = data.{{ $scope.TitlelizeProperty }}.ValueString() } {{- end }} {{- end }} @@ -113,23 +113,10 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L err := List{{ $.ResourceName }}s( r.Client, filterString, -{{- range $identity := $.IdentityProperties }} - {{ $identity.CamelizeProperty }}, +{{- range $scope := $.ListScopeProperties }} + {{ $scope.CamelizeProperty }}, {{- end }} func(rd *schema.ResourceData) error { -{{- $hasListName := false -}} -{{- range $identity := $.IdentityProperties }} -{{- if eq $identity.Name "name" }} -{{- $hasListName = true -}} -{{- end }} -{{- end }} -{{- if $hasListName }} - if name != "" { - if n, ok := rd.GetOk("name"); !ok || n.(string) != name { - return nil - } - } -{{- end }} result := req.NewListResult(ctx) if n, ok := rd.GetOk("name"); ok { @@ -159,19 +146,18 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L } func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, -{{- range $identity := $.IdentityProperties }} - {{ $identity.CamelizeProperty }} string, +{{- range $scope := $.ListScopeProperties }} + {{ $scope.CamelizeProperty }} string, {{- end }} callback func(*schema.ResourceData) error, ) error { resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) - // ReplaceVars expands {{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}} (product default_base_url) and base_url using resourceData. - // base_url often omits vars that still appear in the base path (e.g. {{"{{"}}location{{"}}"}} in the host, {{"{{"}}project{{"}}"}} only in the path). - // Set every resolved list identity on resourceData before building the list URL. -{{- range $identity := $.IdentityProperties }} - if {{ $identity.CamelizeProperty }} != "" { - if err := resourceData.Set("{{ underscore $identity.Name }}", {{ $identity.CamelizeProperty }}); err != nil { - return fmt.Errorf("error setting {{ underscore $identity.Name }} on temporary resource data: %w", err) + // ReplaceVars expands {{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}} (product base_url) and base_url using resourceData. + // Set every resolved list scope parameter on resourceData before building the list URL. +{{- range $scope := $.ListScopeProperties }} + if {{ $scope.CamelizeProperty }} != "" { + if err := resourceData.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $scope.Name }} on temporary resource data: %w", err) } } {{- end }} @@ -220,16 +206,16 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, {{- end }} {{- end }} {{- end }} -{{- /* List scope (project/region/zone/location) is constant for the whole list call; re-apply from ListXxxs args so ReplaceVars sees correct values after Flatten mutates shared d. */ -}} +{{- /* Re-apply list scope values so ReplaceVars sees correct values after Flatten mutates shared d. */ -}} {{- $liProject := false -}} {{- $liRegion := false -}} {{- $liZone := false -}} {{- $liLocation := false -}} -{{- range $identity := $.IdentityProperties }} -{{- if eq $identity.Name "project" }}{{- $liProject = true -}}{{- end }} -{{- if eq $identity.Name "region" }}{{- $liRegion = true -}}{{- end }} -{{- if eq $identity.Name "zone" }}{{- $liZone = true -}}{{- end }} -{{- if eq $identity.Name "location" }}{{- $liLocation = true -}}{{- end }} +{{- range $scope := $.ListScopeProperties }} +{{- if eq $scope.Name "project" }}{{- $liProject = true -}}{{- end }} +{{- if eq $scope.Name "region" }}{{- $liRegion = true -}}{{- end }} +{{- if eq $scope.Name "zone" }}{{- $liZone = true -}}{{- end }} +{{- if eq $scope.Name "location" }}{{- $liLocation = true -}}{{- end }} {{- end }} {{- if $.HasProject }} var itemProject string @@ -251,11 +237,11 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, } {{- end }} {{- end }} -{{- range $identity := $.IdentityProperties }} -{{- if or (eq $identity.Name "region") (eq $identity.Name "zone") (eq $identity.Name "location") }} - if {{ $identity.CamelizeProperty }} != "" { - if err := d.Set("{{ underscore $identity.Name }}", {{ $identity.CamelizeProperty }}); err != nil { - return fmt.Errorf("error setting {{ underscore $identity.Name }} on list item temporary resource data: %w", err) +{{- range $scope := $.ListScopeProperties }} +{{- if or (eq $scope.Name "region") (eq $scope.Name "zone") (eq $scope.Name "location") }} + if {{ $scope.CamelizeProperty }} != "" { + if err := d.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $scope.Name }} on list item temporary resource data: %w", err) } } {{- end }} From 7a5099879801568eb2b294571130ea1dd53f0e3a Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 15:02:04 -0700 Subject: [PATCH 046/100] remove filter field from list resource generation --- mmv1/templates/terraform/list_resource.go.tmpl | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 826164fd4ea0..5f55740058f2 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -65,9 +65,6 @@ func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context Optional: true, }, {{- end }} - "filter": listschema.StringAttribute{ - Optional: true, - }, }, } } @@ -76,7 +73,6 @@ type {{ $.ResourceName -}}ListModel struct { {{- range $scope := $.ListScopeProperties }} {{ $scope.TitlelizeProperty }} types.String `tfsdk:"{{ underscore $scope.Name }}"` {{- end }} - Filter types.String `tfsdk:"filter"` } func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { @@ -104,15 +100,9 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L {{- end }} {{- end }} - filterString := "" - if !data.Filter.IsNull() && !data.Filter.IsUnknown() { - filterString = data.Filter.ValueString() - } - stream.Results = func(push func(list.ListResult) bool) { err := List{{ $.ResourceName }}s( r.Client, - filterString, {{- range $scope := $.ListScopeProperties }} {{ $scope.CamelizeProperty }}, {{- end }} @@ -145,7 +135,7 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L } } -func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, +func List{{ $.ResourceName }}s(config *transport_tpg.Config, {{- range $scope := $.ListScopeProperties }} {{ $scope.CamelizeProperty }} string, {{- end }} @@ -187,7 +177,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, filter string, billingProject, userAgent, "{{ $.ResourceListKey }}", - filter, + "", func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { {{- if $.ExcludeRead }} return fmt.Errorf("list resource for {{ $.Name }} requires read support (resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") From d4f9e64e279738773ae9ab67364ae43944b994ea Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Fri, 10 Apr 2026 15:11:34 -0700 Subject: [PATCH 047/100] split list_resource.go.tmpl into multiple templates --- mmv1/provider/terraform.go | 6 +- .../templates/terraform/list_resource.go.tmpl | 174 +----------------- ...list_resource_list_pages_flattener.go.tmpl | 127 +++++++++++++ .../terraform/list_resource_method.go.tmpl | 51 +++++ 4 files changed, 184 insertions(+), 174 deletions(-) create mode 100644 mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl create mode 100644 mmv1/templates/terraform/list_resource_method.go.tmpl diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index e7ea8d66d670..fe6f99b74800 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -160,7 +160,11 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD log.Fatalf("generate_list_resource requires identity support; remove exclude_identity_generation from resource %q or disable generate_list_resource", object.Name) } targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_resource_%s.go", t.ResourceGoFilename(object))) - templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, "templates/terraform/list_resource.go.tmpl") + templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, + "templates/terraform/list_resource.go.tmpl", + "templates/terraform/list_resource_method.go.tmpl", + "templates/terraform/list_resource_list_pages_flattener.go.tmpl", + ) } } diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 5f55740058f2..ba26c13c96fa 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -135,176 +135,4 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L } } -func List{{ $.ResourceName }}s(config *transport_tpg.Config, -{{- range $scope := $.ListScopeProperties }} - {{ $scope.CamelizeProperty }} string, -{{- end }} - callback func(*schema.ResourceData) error, -) error { - resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) - // ReplaceVars expands {{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}} (product base_url) and base_url using resourceData. - // Set every resolved list scope parameter on resourceData before building the list URL. -{{- range $scope := $.ListScopeProperties }} - if {{ $scope.CamelizeProperty }} != "" { - if err := resourceData.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { - return fmt.Errorf("error setting {{ underscore $scope.Name }} on temporary resource data: %w", err) - } - } -{{- end }} - - url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(resourceData, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.BaseUrl}}") - if err != nil { - return err - } - - billingProject := "" - if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { - billingProject = parts[1] - } - if bp, err := tpgresource.GetBillingProject(resourceData, config); err == nil { - billingProject = bp - } - - userAgent, err := tpgresource.GenerateUserAgentString(resourceData, config.UserAgent) - if err != nil { - return err - } - - return transport_tpg.ListPages( - config, - resourceData, - url, - billingProject, - userAgent, - "{{ $.ResourceListKey }}", - "", - func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { -{{- if $.ExcludeRead }} - return fmt.Errorf("list resource for {{ $.Name }} requires read support (resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") -{{- else }} - meta := interface{}(config) -{{- if $.VirtualFields }} - - // Explicitly set virtual fields to default values if unset (same order as resource{{ $.ResourceName }}Read) -{{- range $prop := $.VirtualFields }} -{{- if not (eq $prop.DefaultValue nil) }} - if _, ok := d.GetOkExists("{{ $prop.Name -}}"); !ok { - if err := d.Set("{{ $prop.Name -}}", {{ $prop.GoLiteral $prop.DefaultValue -}}); err != nil { - return fmt.Errorf("Error setting {{ $prop.Name -}}: %s", err) - } - } -{{- end }} -{{- end }} -{{- end }} -{{- /* Re-apply list scope values so ReplaceVars sees correct values after Flatten mutates shared d. */ -}} -{{- $liProject := false -}} -{{- $liRegion := false -}} -{{- $liZone := false -}} -{{- $liLocation := false -}} -{{- range $scope := $.ListScopeProperties }} -{{- if eq $scope.Name "project" }}{{- $liProject = true -}}{{- end }} -{{- if eq $scope.Name "region" }}{{- $liRegion = true -}}{{- end }} -{{- if eq $scope.Name "zone" }}{{- $liZone = true -}}{{- end }} -{{- if eq $scope.Name "location" }}{{- $liLocation = true -}}{{- end }} -{{- end }} -{{- if $.HasProject }} - var itemProject string -{{- if $liProject }} - itemProject = project - if itemProject != "" { - if err := d.Set("project", itemProject); err != nil { - return fmt.Errorf("error setting project on list item temporary resource data: %w", err) - } - } -{{- else }} - var errProj error - itemProject, errProj = tpgresource.GetProject(d, config) - if errProj != nil { - return fmt.Errorf("error fetching project for {{ $.Name }}: %w", errProj) - } - if err := d.Set("project", itemProject); err != nil { - return fmt.Errorf("error setting project on list item temporary resource data: %w", err) - } -{{- end }} -{{- end }} -{{- range $scope := $.ListScopeProperties }} -{{- if or (eq $scope.Name "region") (eq $scope.Name "zone") (eq $scope.Name "location") }} - if {{ $scope.CamelizeProperty }} != "" { - if err := d.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { - return fmt.Errorf("error setting {{ underscore $scope.Name }} on list item temporary resource data: %w", err) - } - } -{{- end }} -{{- end }} -{{- if and $.HasRegion (not $liRegion) }} - region, err := tpgresource.GetRegion(d, config) - if err != nil { - return err - } - if err := d.Set("region", region); err != nil { - return fmt.Errorf("error setting region on list item temporary resource data: %w", err) - } -{{- end }} -{{- if and $.HasZone (not $liZone) }} - zone, err := tpgresource.GetZone(d, config) - if err != nil { - return err - } - if err := d.Set("zone", zone); err != nil { - return fmt.Errorf("error setting zone on list item temporary resource data: %w", err) - } -{{- end }} -{{- if and $.HasLocation (not $liLocation) }} - location, err := tpgresource.GetLocation(d, config) - if err != nil { - return err - } - if err := d.Set("location", location); err != nil { - return fmt.Errorf("error setting location on list item temporary resource data: %w", err) - } -{{- end }} - - itemUserAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) - if err != nil { - return err - } - - readURL, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") - if err != nil { - return err - } - - itemBillingProject := "" -{{- if $.HasProject }} -{{- if $.LegacyLongFormProject }} - itemBillingProject = strings.TrimPrefix(itemProject, "projects/") -{{- else }} - itemBillingProject = itemProject -{{- end }} -{{- end }} -{{- if $.SupportsIndirectUserProjectOverride }} - if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(readURL); parts != nil { - itemBillingProject = parts[1] - } -{{- end }} - if bp, err := tpgresource.GetBillingProject(d, config); err == nil { - itemBillingProject = bp - } - - headers := make(http.Header) - - if err := resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}itemProject,{{ end }} itemUserAgent, itemBillingProject, readURL, headers); err != nil { - return err - } - - id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) - return nil -{{- end }} - }, - callback, - ) -} +{{ template "listResourceMethod" $ }} diff --git a/mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl b/mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl new file mode 100644 index 000000000000..4b1c92dac849 --- /dev/null +++ b/mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl @@ -0,0 +1,127 @@ +{{ define "listResourceListPagesFlattener" }} +{{- if $.ExcludeRead }} + return fmt.Errorf("list resource for {{ $.Name }} requires read support (resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") +{{- else }} + meta := interface{}(config) +{{- if $.VirtualFields }} + + // Explicitly set virtual fields to default values if unset (same order as resource{{ $.ResourceName }}Read) +{{- range $prop := $.VirtualFields }} +{{- if not (eq $prop.DefaultValue nil) }} + if _, ok := d.GetOkExists("{{ $prop.Name -}}"); !ok { + if err := d.Set("{{ $prop.Name -}}", {{ $prop.GoLiteral $prop.DefaultValue -}}); err != nil { + return fmt.Errorf("Error setting {{ $prop.Name -}}: %s", err) + } + } +{{- end }} +{{- end }} +{{- end }} +{{- /* Re-apply list scope values so ReplaceVars sees correct values after Flatten mutates shared d. */ -}} +{{- $liProject := false -}} +{{- $liRegion := false -}} +{{- $liZone := false -}} +{{- $liLocation := false -}} +{{- range $scope := $.ListScopeProperties }} +{{- if eq $scope.Name "project" }}{{- $liProject = true -}}{{- end }} +{{- if eq $scope.Name "region" }}{{- $liRegion = true -}}{{- end }} +{{- if eq $scope.Name "zone" }}{{- $liZone = true -}}{{- end }} +{{- if eq $scope.Name "location" }}{{- $liLocation = true -}}{{- end }} +{{- end }} +{{- if $.HasProject }} + var itemProject string +{{- if $liProject }} + itemProject = project + if itemProject != "" { + if err := d.Set("project", itemProject); err != nil { + return fmt.Errorf("error setting project on list item temporary resource data: %w", err) + } + } +{{- else }} + var errProj error + itemProject, errProj = tpgresource.GetProject(d, config) + if errProj != nil { + return fmt.Errorf("error fetching project for {{ $.Name }}: %w", errProj) + } + if err := d.Set("project", itemProject); err != nil { + return fmt.Errorf("error setting project on list item temporary resource data: %w", err) + } +{{- end }} +{{- end }} +{{- range $scope := $.ListScopeProperties }} +{{- if or (eq $scope.Name "region") (eq $scope.Name "zone") (eq $scope.Name "location") }} + if {{ $scope.CamelizeProperty }} != "" { + if err := d.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $scope.Name }} on list item temporary resource data: %w", err) + } + } +{{- end }} +{{- end }} +{{- if and $.HasRegion (not $liRegion) }} + region, err := tpgresource.GetRegion(d, config) + if err != nil { + return err + } + if err := d.Set("region", region); err != nil { + return fmt.Errorf("error setting region on list item temporary resource data: %w", err) + } +{{- end }} +{{- if and $.HasZone (not $liZone) }} + zone, err := tpgresource.GetZone(d, config) + if err != nil { + return err + } + if err := d.Set("zone", zone); err != nil { + return fmt.Errorf("error setting zone on list item temporary resource data: %w", err) + } +{{- end }} +{{- if and $.HasLocation (not $liLocation) }} + location, err := tpgresource.GetLocation(d, config) + if err != nil { + return err + } + if err := d.Set("location", location); err != nil { + return fmt.Errorf("error setting location on list item temporary resource data: %w", err) + } +{{- end }} + + itemUserAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + readURL, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") + if err != nil { + return err + } + + itemBillingProject := "" +{{- if $.HasProject }} +{{- if $.LegacyLongFormProject }} + itemBillingProject = strings.TrimPrefix(itemProject, "projects/") +{{- else }} + itemBillingProject = itemProject +{{- end }} +{{- end }} +{{- if $.SupportsIndirectUserProjectOverride }} + if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(readURL); parts != nil { + itemBillingProject = parts[1] + } +{{- end }} + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + itemBillingProject = bp + } + + headers := make(http.Header) + + if err := resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}itemProject,{{ end }} itemUserAgent, itemBillingProject, readURL, headers); err != nil { + return err + } + + id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + return nil +{{- end }} +{{ end }} diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl new file mode 100644 index 000000000000..e95c1453059e --- /dev/null +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -0,0 +1,51 @@ +{{ define "listResourceMethod" }} +func List{{ $.ResourceName }}s(config *transport_tpg.Config, +{{- range $scope := $.ListScopeProperties }} + {{ $scope.CamelizeProperty }} string, +{{- end }} + callback func(*schema.ResourceData) error, +) error { + resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) + // ReplaceVars expands {{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}} (product base_url) and base_url using resourceData. + // Set every resolved list scope parameter on resourceData before building the list URL. +{{- range $scope := $.ListScopeProperties }} + if {{ $scope.CamelizeProperty }} != "" { + if err := resourceData.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $scope.Name }} on temporary resource data: %w", err) + } + } +{{- end }} + + url, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(resourceData, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.BaseUrl}}") + if err != nil { + return err + } + + billingProject := "" + if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { + billingProject = parts[1] + } + if bp, err := tpgresource.GetBillingProject(resourceData, config); err == nil { + billingProject = bp + } + + userAgent, err := tpgresource.GenerateUserAgentString(resourceData, config.UserAgent) + if err != nil { + return err + } + + return transport_tpg.ListPages( + config, + resourceData, + url, + billingProject, + userAgent, + "{{ $.ResourceListKey }}", + "", + func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { +{{ template "listResourceListPagesFlattener" $ }} + }, + callback, + ) +} +{{ end }} From c492c9d9666f3ae96dd6ed52074fb2bb667d29bd Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 09:47:55 -0700 Subject: [PATCH 048/100] migrate to framework_mmv1_resources template --- .../fwprovider/framework_provider_mmv1_resources.go.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl index ba2eb00d313f..bce0bceb985c 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl @@ -23,4 +23,5 @@ var generatedListResources = []func() list.ListResource{ var handwrittenListResources = []func() list.ListResource{ listResourceFunc(resourcemanager.NewGoogleServiceAccountListResource()), + listResourceFunc(resourcemanager.NewGoogleProjectServiceListResource()), } From b74540bdadba0ccd4d49181a97d663c85e122f83 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 09:56:11 -0700 Subject: [PATCH 049/100] remove duplicate definitions after rebase --- .../terraform/tpgresource/list_resource.go | 48 +------------------ 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index a70dc2db0dee..14f30cedfda0 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -154,7 +154,8 @@ func (listR *ListResourceMetadata) GetZone(override types.String) string { return listR.Zone } -// GetLocation: list config override, else provider default region. +// GetLocation returns the location from the list block override if set and non-empty, +// otherwise the provider-level region (typical default for regional APIs). func (listR *ListResourceMetadata) GetLocation(override types.String) string { if !override.IsNull() && !override.IsUnknown() { if v := override.ValueString(); v != "" { @@ -249,51 +250,6 @@ func (listR *ListResourceMetadata) SetResult(ctx context.Context, includeResourc return nil } -// ResolveProject returns the project from override if it is set and non-empty, -// otherwise falls back to the provider-level default. -func (r *ListResourceMetadata) GetProject(override types.String) string { - if !override.IsNull() && !override.IsUnknown() { - if v := override.ValueString(); v != "" { - return v - } - } - return r.ProjectId -} - -// ResolveRegion returns the region from override if it is set and non-empty, -// otherwise falls back to the provider-level default. -func (r *ListResourceMetadata) GetRegion(override types.String) string { - if !override.IsNull() && !override.IsUnknown() { - if v := override.ValueString(); v != "" { - return v - } - } - return r.Region -} - -// ResolveZone returns the zone from override if it is set and non-empty, -// otherwise falls back to the provider-level default. -func (r *ListResourceMetadata) GetZone(override types.String) string { - if !override.IsNull() && !override.IsUnknown() { - if v := override.ValueString(); v != "" { - return v - } - } - return r.Zone -} - -// GetLocation returns the location from the list block override if set and non-empty, -// otherwise falls back to the provider-level region (typical default for regional APIs). -// Used by MM-generated list resources together with GetProject/GetRegion/GetZone + SetIdentityFields above. -func (r *ListResourceMetadata) GetLocation(override types.String) string { - if !override.IsNull() && !override.IsUnknown() { - if v := override.ValueString(); v != "" { - return v - } - } - return r.Region -} - func SetIdentityFields(ctx context.Context, result *list.ListResult, rd *schema.ResourceData, fields map[string]string) error { identity, err := rd.Identity() if err != nil { From 74c276691358f0a98f137e3212046f3cbd93a4bf Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 09:59:04 -0700 Subject: [PATCH 050/100] update to use ListPagesOptions struct --- .../terraform/list_resource_method.go.tmpl | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index e95c1453059e..6068541fa237 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -34,18 +34,17 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return err } - return transport_tpg.ListPages( - config, - resourceData, - url, - billingProject, - userAgent, - "{{ $.ResourceListKey }}", - "", - func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { + return transport_tpg.ListPages(transport_tpg.ListPagesOptions{ + Config: config, + TempData: resourceData, + ListURL: url, + BillingProject: billingProject, + UserAgent: userAgent, + ItemName: "{{ $.ResourceListKey }}", + Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { {{ template "listResourceListPagesFlattener" $ }} }, - callback, - ) + Callback: callback, + }) } {{ end }} From 2aa8b8e6d3086953c2626e3b0652a5dfb0400416 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 10:16:21 -0700 Subject: [PATCH 051/100] match list_utils changes introduced in upstream magic-modules --- .../templates/terraform/list_resource.go.tmpl | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index ba26c13c96fa..4de4182df268 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -29,8 +29,8 @@ import ( "strings" {{- end }} + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/list" - listschema "github.com/hashicorp/terraform-plugin-framework/list/schema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -39,59 +39,56 @@ import ( transport_tpg "{{ $.ImportPath }}/transport" ) -var _ tpgresource.ListResourceWithRawV5Schemas = &{{ $.ResourceName -}}ListResource{} +var _ list.ListResource = &{{ $.ResourceName -}}ListResource{} type {{ $.ResourceName -}}ListResource struct { tpgresource.ListResourceMetadata } func New{{ $.ResourceName -}}ListResource() list.ListResource { - r := &{{ $.ResourceName -}}ListResource{} - r.TypeName = "{{ $.TerraformName }}" - r.ResourceSchema = Resource{{ $.ResourceName -}}() - r.IdentityAttributes = []string{ -{{- range $identity := $.IdentityProperties }} - "{{ underscore $identity.Name }}", -{{- end }} - } - return r -} - -func (r *{{ $.ResourceName -}}ListResource) ListResourceConfigSchema(ctx context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) { - resp.Schema = listschema.Schema{ - Attributes: map[string]listschema.Attribute{ + listR := &{{ $.ResourceName -}}ListResource{} + listR.TypeName = "{{ $.TerraformName }}" + listR.SDKv2Resource = Resource{{ $.ResourceName -}}() + listR.ListConfigFields = []tpgresource.ListConfigField{ {{- range $scope := $.ListScopeProperties }} - "{{ underscore $scope.Name }}": listschema.StringAttribute{ - Optional: true, - }, + {Name: "{{ underscore $scope.Name }}", Kind: tpgresource.ListConfigKindString, Optional: true}, {{- end }} - }, } + return listR } +// {{ $.ResourceName }}ListModel matches ListResourceMetadata.ListConfigFields (tfsdk names and types). type {{ $.ResourceName -}}ListModel struct { {{- range $scope := $.ListScopeProperties }} {{ $scope.TitlelizeProperty }} types.String `tfsdk:"{{ underscore $scope.Name }}"` {{- end }} } -func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { +func (listR *{{ $.ResourceName -}}ListResource) List(ctx context.Context, listReq list.ListRequest, stream *list.ListResultsStream) { var data {{ $.ResourceName -}}ListModel - diags := req.Config.Get(ctx, &data) + diags := listReq.Config.Get(ctx, &data) if diags.HasError() { stream.Results = list.ListResultsStreamDiagnostics(diags) return } + if listR.Client == nil { + diags = append(diags, diag.NewErrorDiagnostic( + "Provider not configured", + "The Google provider client is not available; ensure the provider is configured (e.g. credentials and default project).", + )) + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } {{- range $scope := $.ListScopeProperties }} {{- if eq $scope.Name "project" }} - {{ $scope.CamelizeProperty }} := r.GetProject(data.{{ $scope.TitlelizeProperty }}) + {{ $scope.CamelizeProperty }} := listR.GetProject(data.{{ $scope.TitlelizeProperty }}) {{- else if eq $scope.Name "region" }} - {{ $scope.CamelizeProperty }} := r.GetRegion(data.{{ $scope.TitlelizeProperty }}) + {{ $scope.CamelizeProperty }} := listR.GetRegion(data.{{ $scope.TitlelizeProperty }}) {{- else if eq $scope.Name "zone" }} - {{ $scope.CamelizeProperty }} := r.GetZone(data.{{ $scope.TitlelizeProperty }}) + {{ $scope.CamelizeProperty }} := listR.GetZone(data.{{ $scope.TitlelizeProperty }}) {{- else if eq $scope.Name "location" }} - {{ $scope.CamelizeProperty }} := r.GetLocation(data.{{ $scope.TitlelizeProperty }}) + {{ $scope.CamelizeProperty }} := listR.GetLocation(data.{{ $scope.TitlelizeProperty }}) {{- else }} var {{ $scope.CamelizeProperty }} string if !data.{{ $scope.TitlelizeProperty }}.IsNull() && !data.{{ $scope.TitlelizeProperty }}.IsUnknown() { @@ -102,12 +99,12 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L stream.Results = func(push func(list.ListResult) bool) { err := List{{ $.ResourceName }}s( - r.Client, + listR.Client, {{- range $scope := $.ListScopeProperties }} {{ $scope.CamelizeProperty }}, {{- end }} func(rd *schema.ResourceData) error { - result := req.NewListResult(ctx) + result := listReq.NewListResult(ctx) if n, ok := rd.GetOk("name"); ok { if s, ok := n.(string); ok { @@ -115,7 +112,7 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L } } - if err := r.SetResult(ctx, req.IncludeResource, &result, rd); err != nil { + if err := listR.SetResult(ctx, listReq.IncludeResource, &result, rd); err != nil { return err } @@ -127,11 +124,10 @@ func (r *{{ $.ResourceName -}}ListResource) List(ctx context.Context, req list.L ) if err != nil { diags.AddError("API Error", err.Error()) - result := req.NewListResult(ctx) + result := listReq.NewListResult(ctx) result.Diagnostics = diags push(result) } - stream.Results = list.ListResultsStreamDiagnostics(diags) } } From abad6590c9d2c781ecff5a69c3b5b1ffa08d0cb6 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 11:37:38 -0700 Subject: [PATCH 052/100] refactors to allow for reuse of resourceFlattener in list resources + setid prior to flattener return --- mmv1/provider/terraform.go | 1 - ...list_resource_list_pages_flattener.go.tmpl | 127 ------------------ .../terraform/list_resource_method.go.tmpl | 35 ++++- .../terraform/transport/transport.go | 3 +- 4 files changed, 35 insertions(+), 131 deletions(-) delete mode 100644 mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index fe6f99b74800..4632e3dc125a 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -163,7 +163,6 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, "templates/terraform/list_resource.go.tmpl", "templates/terraform/list_resource_method.go.tmpl", - "templates/terraform/list_resource_list_pages_flattener.go.tmpl", ) } } diff --git a/mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl b/mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl deleted file mode 100644 index 4b1c92dac849..000000000000 --- a/mmv1/templates/terraform/list_resource_list_pages_flattener.go.tmpl +++ /dev/null @@ -1,127 +0,0 @@ -{{ define "listResourceListPagesFlattener" }} -{{- if $.ExcludeRead }} - return fmt.Errorf("list resource for {{ $.Name }} requires read support (resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") -{{- else }} - meta := interface{}(config) -{{- if $.VirtualFields }} - - // Explicitly set virtual fields to default values if unset (same order as resource{{ $.ResourceName }}Read) -{{- range $prop := $.VirtualFields }} -{{- if not (eq $prop.DefaultValue nil) }} - if _, ok := d.GetOkExists("{{ $prop.Name -}}"); !ok { - if err := d.Set("{{ $prop.Name -}}", {{ $prop.GoLiteral $prop.DefaultValue -}}); err != nil { - return fmt.Errorf("Error setting {{ $prop.Name -}}: %s", err) - } - } -{{- end }} -{{- end }} -{{- end }} -{{- /* Re-apply list scope values so ReplaceVars sees correct values after Flatten mutates shared d. */ -}} -{{- $liProject := false -}} -{{- $liRegion := false -}} -{{- $liZone := false -}} -{{- $liLocation := false -}} -{{- range $scope := $.ListScopeProperties }} -{{- if eq $scope.Name "project" }}{{- $liProject = true -}}{{- end }} -{{- if eq $scope.Name "region" }}{{- $liRegion = true -}}{{- end }} -{{- if eq $scope.Name "zone" }}{{- $liZone = true -}}{{- end }} -{{- if eq $scope.Name "location" }}{{- $liLocation = true -}}{{- end }} -{{- end }} -{{- if $.HasProject }} - var itemProject string -{{- if $liProject }} - itemProject = project - if itemProject != "" { - if err := d.Set("project", itemProject); err != nil { - return fmt.Errorf("error setting project on list item temporary resource data: %w", err) - } - } -{{- else }} - var errProj error - itemProject, errProj = tpgresource.GetProject(d, config) - if errProj != nil { - return fmt.Errorf("error fetching project for {{ $.Name }}: %w", errProj) - } - if err := d.Set("project", itemProject); err != nil { - return fmt.Errorf("error setting project on list item temporary resource data: %w", err) - } -{{- end }} -{{- end }} -{{- range $scope := $.ListScopeProperties }} -{{- if or (eq $scope.Name "region") (eq $scope.Name "zone") (eq $scope.Name "location") }} - if {{ $scope.CamelizeProperty }} != "" { - if err := d.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { - return fmt.Errorf("error setting {{ underscore $scope.Name }} on list item temporary resource data: %w", err) - } - } -{{- end }} -{{- end }} -{{- if and $.HasRegion (not $liRegion) }} - region, err := tpgresource.GetRegion(d, config) - if err != nil { - return err - } - if err := d.Set("region", region); err != nil { - return fmt.Errorf("error setting region on list item temporary resource data: %w", err) - } -{{- end }} -{{- if and $.HasZone (not $liZone) }} - zone, err := tpgresource.GetZone(d, config) - if err != nil { - return err - } - if err := d.Set("zone", zone); err != nil { - return fmt.Errorf("error setting zone on list item temporary resource data: %w", err) - } -{{- end }} -{{- if and $.HasLocation (not $liLocation) }} - location, err := tpgresource.GetLocation(d, config) - if err != nil { - return err - } - if err := d.Set("location", location); err != nil { - return fmt.Errorf("error setting location on list item temporary resource data: %w", err) - } -{{- end }} - - itemUserAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) - if err != nil { - return err - } - - readURL, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") - if err != nil { - return err - } - - itemBillingProject := "" -{{- if $.HasProject }} -{{- if $.LegacyLongFormProject }} - itemBillingProject = strings.TrimPrefix(itemProject, "projects/") -{{- else }} - itemBillingProject = itemProject -{{- end }} -{{- end }} -{{- if $.SupportsIndirectUserProjectOverride }} - if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(readURL); parts != nil { - itemBillingProject = parts[1] - } -{{- end }} - if bp, err := tpgresource.GetBillingProject(d, config); err == nil { - itemBillingProject = bp - } - - headers := make(http.Header) - - if err := resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}itemProject,{{ end }} itemUserAgent, itemBillingProject, readURL, headers); err != nil { - return err - } - - id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) - return nil -{{- end }} -{{ end }} diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 6068541fa237..5bd31c8f3edd 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -41,8 +41,39 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, BillingProject: billingProject, UserAgent: userAgent, ItemName: "{{ $.ResourceListKey }}", - Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { -{{ template "listResourceListPagesFlattener" $ }} + Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config, _ ...string) error { +{{- if $.ExcludeRead }} + return fmt.Errorf("list resource for {{ $.Name }} requires read support (Resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") +{{- else }} + meta := interface{}(config) + headers := make(http.Header) +{{- range $scope := $.ListScopeProperties }} + if {{ $scope.CamelizeProperty }} != "" { + if err := d.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { + return fmt.Errorf("error setting {{ underscore $scope.Name }} on list item temporary resource data: %w", err) + } + } +{{- end }} +{{- if $.HasProject }} + itemProject, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("error fetching project for {{ $.Name }}: %w", err) + } +{{- end }} + readURL, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") + if err != nil { + return err + } + if err := Resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}itemProject,{{ end }} userAgent, billingProject, readURL, headers); err != nil { + return err + } + id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + return nil +{{- end }} }, Callback: callback, }) diff --git a/mmv1/third_party/terraform/transport/transport.go b/mmv1/third_party/terraform/transport/transport.go index d6dae5f69c6c..f30bb3d207ac 100644 --- a/mmv1/third_party/terraform/transport/transport.go +++ b/mmv1/third_party/terraform/transport/transport.go @@ -207,7 +207,8 @@ type ListPagesOptions struct { UserAgent string ItemName string Filter string - Flattener func(item map[string]interface{}, d *schema.ResourceData, config *Config) error + // Flattener maps one list JSON object onto TempData; optional trailing args reserved for callers. + Flattener func(item map[string]interface{}, d *schema.ResourceData, config *Config, args ...string) error Callback func(rd *schema.ResourceData) error } From fcbbe70856e801e2addc18897b6f17bbe60b6b60 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 11:45:19 -0700 Subject: [PATCH 053/100] remove common~copy changes --- mmv1/provider/terraform/common~compile.yaml | 1 - mmv1/provider/terraform/common~copy.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/mmv1/provider/terraform/common~compile.yaml b/mmv1/provider/terraform/common~compile.yaml index 391870676f33..266818c89957 100644 --- a/mmv1/provider/terraform/common~compile.yaml +++ b/mmv1/provider/terraform/common~compile.yaml @@ -85,7 +85,6 @@ <% Dir["third_party/terraform/transport/*.go.erb"].each do |file_path| fname = file_path.split('/')[-1] - next if fname == "cloud_clients.go.erb" -%> '<%= dir -%>/transport/<%= fname.delete_suffix(".erb") -%>': 'third_party/terraform/transport/<%= fname -%>' <% end -%> diff --git a/mmv1/provider/terraform/common~copy.yaml b/mmv1/provider/terraform/common~copy.yaml index a6fc5e9c1e42..1784bffb4170 100644 --- a/mmv1/provider/terraform/common~copy.yaml +++ b/mmv1/provider/terraform/common~copy.yaml @@ -83,7 +83,6 @@ <% Dir["third_party/terraform/transport/*.go"].each do |file_path| fname = file_path.split('/')[-1] - next if fname == "cloud_clients.go" -%> '<%= dir -%>/transport/<%= fname -%>': 'third_party/terraform/transport/<%= fname -%>' <% end -%> From 56a6d8529892d3a2d799fab656a93e22dde1ffce Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 11:48:37 -0700 Subject: [PATCH 054/100] more common~copy removals --- mmv1/provider/terraform.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 4632e3dc125a..ef129f7e5c61 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -549,10 +549,6 @@ func (t Terraform) getCopyFilesInFolder(folderPath, targetDir string) map[string if di.Name() == "gha-branch-renaming.png" || di.Name() == "clock-timings-of-branch-making-and-usage.png" { return nil } - // Handwritten in the provider; do not copy from third_party (see getCompileFilesInFolder for .tmpl). - if di.Name() == "cloud_clients.go" { - return nil - } fname := strings.TrimPrefix(path, "third_party/terraform/") target := fname @@ -665,10 +661,6 @@ func (t Terraform) getCompileFilesInFolder(folderPath, targetDir string) map[str return err } if !di.IsDir() && strings.HasSuffix(di.Name(), ".tmpl") { - // Provider maintains google/transport/cloud_clients.go by hand while phasing out generated clients. - if di.Name() == "cloud_clients.go.tmpl" { - return nil - } fname := strings.TrimPrefix(path, "third_party/terraform/") fname = strings.TrimSuffix(fname, ".tmpl") target := fname From 0a26a144e01dc3b9f022abc80510a41a21e86fe0 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 13:02:20 -0700 Subject: [PATCH 055/100] remove what is unnecessary --- mmv1/templates/terraform/resource.go.tmpl | 14 ++++++----- .../terraform/tpgresource/list_resource.go | 23 +------------------ 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl index 98694c2ad7e6..9e5f4edca5c0 100644 --- a/mmv1/templates/terraform/resource.go.tmpl +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -827,16 +827,18 @@ func resource{{ $.ResourceName -}}Read(d *schema.ResourceData, meta interface{}) if err == nil && identity != nil { {{- range $p := $.IdentityProperties }} {{ if eq $p.Type "Integer" -}} - if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { - if err := identity.Set("{{ underscore $p.Name}}", v.(int)); err != nil { + if _, ok := identity.GetOk("{{ underscore $p.Name}}");!ok { + err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(int)) + if err != nil { return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) } } {{- else -}} - if v, ok := d.GetOk("{{ underscore $p.Name}}"); ok { - if err := identity.Set("{{ underscore $p.Name}}", v.(string)); err != nil { - return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) - } + if v, ok := identity.GetOk("{{ underscore $p.Name}}");!ok && v == "" { + err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string)) + if err != nil { + return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err) + } } {{- end -}} {{- end }} diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index 14f30cedfda0..2dec34b042aa 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -154,8 +154,7 @@ func (listR *ListResourceMetadata) GetZone(override types.String) string { return listR.Zone } -// GetLocation returns the location from the list block override if set and non-empty, -// otherwise the provider-level region (typical default for regional APIs). +// GetLocation: list config override, else provider default region. func (listR *ListResourceMetadata) GetLocation(override types.String) string { if !override.IsNull() && !override.IsUnknown() { if v := override.ValueString(); v != "" { @@ -249,23 +248,3 @@ func (listR *ListResourceMetadata) SetResult(ctx context.Context, includeResourc return nil } - -func SetIdentityFields(ctx context.Context, result *list.ListResult, rd *schema.ResourceData, fields map[string]string) error { - identity, err := rd.Identity() - if err != nil { - return fmt.Errorf("error getting identity: %s", err) - } - for k, v := range fields { - if err := identity.Set(k, v); err != nil { - return fmt.Errorf("error setting identity field %q: %s", k, err) - } - } - tfTypeIdentity, err := rd.TfTypeIdentityState() - if err != nil { - return err - } - if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil { - return errors.New("error setting identity") - } - return nil -} From f6cf8118e629b7d7a7c0c2149a694cda38dc6ae8 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 15:30:22 -0700 Subject: [PATCH 056/100] ListResultDisplayName for setting DisplayName of resource in query result --- mmv1/api/resource.go | 20 +++++++++++++++++++ .../templates/terraform/list_resource.go.tmpl | 8 +------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index e572ae48acb8..4b75258b4b77 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -248,6 +248,11 @@ type Resource struct { // If true, generate a list resource for the resource GenerateListResource bool `yaml:"generate_list_resource,omitempty"` + // ListResultDisplayNameKeys lists Terraform schema attribute names (snake_case), in priority order, + // passed to tpgresource.ListResourceMetadata.SetResult as displayNameKeys. Used when + // generate_list_resource is true. If empty, default is ["name"] when a root "name" property exists. + ListResultDisplayNameKeys []string `yaml:"list_result_display_name_keys,omitempty"` + // If true, skip sweeper generation for this resource ExcludeSweeper bool `yaml:"exclude_sweeper,omitempty"` @@ -735,6 +740,21 @@ func (r Resource) ListScopeProperties() []*Type { return props } +// ListResultDisplayNameKeyStrings returns Terraform attribute names for list result DisplayName +// (SetResult variadic args). YAML list_result_display_name_keys overrides; otherwise ["name"] +// when a root user property "name" exists. +func (r Resource) ListResultDisplayNameKeyStrings() []string { + if len(r.ListResultDisplayNameKeys) > 0 { + return r.ListResultDisplayNameKeys + } + for _, p := range r.RootProperties() { + if p.Name == "name" { + return []string{"name"} + } + } + return nil +} + func (r Resource) SensitiveProps() []*Type { props := r.AllNestedProperties(r.RootProperties()) return google.Select(props, func(p *Type) bool { diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 4de4182df268..d81819c7325a 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -106,13 +106,7 @@ func (listR *{{ $.ResourceName -}}ListResource) List(ctx context.Context, listRe func(rd *schema.ResourceData) error { result := listReq.NewListResult(ctx) - if n, ok := rd.GetOk("name"); ok { - if s, ok := n.(string); ok { - result.DisplayName = s - } - } - - if err := listR.SetResult(ctx, listReq.IncludeResource, &result, rd); err != nil { + if err := listR.SetResult(ctx, listReq.IncludeResource, &result, rd{{- range $k := $.ListResultDisplayNameKeyStrings }}, "{{ $k }}"{{- end }}); err != nil { return err } From 84054929e27b27319256fa21f099acd8dadfe3d3 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 15:37:40 -0700 Subject: [PATCH 057/100] initial query test generation implementation --- mmv1/google/template_utils.go | 17 ++- mmv1/provider/template_data.go | 10 ++ mmv1/provider/terraform.go | 35 +++++ .../base_configs/query_test_file.go.tmpl | 123 ++++++++++++++++++ 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl diff --git a/mmv1/google/template_utils.go b/mmv1/google/template_utils.go index f2b66262fe83..72b8392b10b1 100644 --- a/mmv1/google/template_utils.go +++ b/mmv1/google/template_utils.go @@ -20,6 +20,7 @@ import ( "io/fs" "path/filepath" "reflect" + "regexp" "strings" "text/template" @@ -83,8 +84,9 @@ func (t functionsData) templateFunctions() template.FuncMap { "sub": subtract, "plus": plus, "firstSentence": FirstSentence, - "trimTemplate": t.trimTemplate, - "customTemplate": t.customTemplate, + "trimTemplate": t.trimTemplate, + "customTemplate": t.customTemplate, + "existsInBaseUrl": t.existsInBaseUrl, } } @@ -131,6 +133,17 @@ func (t *functionsData) trimTemplate(templatePath string, e any) (string, error) return fmt.Sprintf("%s\n", rs), nil } +// existsInBaseUrl reports whether urlTemplate contains a ReplaceVars-style token {{key}}. +func (t *functionsData) existsInBaseUrl(urlTemplate string, key string) bool { + re := regexp.MustCompile(`\{\{(\w+)\}\}`) + for _, match := range re.FindAllStringSubmatch(urlTemplate, -1) { + if len(match) > 1 && match[1] == key { + return true + } + } + return false +} + func (t functionsData) customTemplate(e any, templatePath string, appendNewline bool) (string, error) { templates := []string{ templatePath, diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index 55183ca1d1fe..cfd5df7d840a 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -282,6 +282,16 @@ func (td *TemplateData) GenerateIamPolicyTestFile(filePath string, resource api. td.GenerateFile(filePath, templatePath, resource, true, templates...) } +// GenerateQueryTestFile emits a Terraform query-mode acceptance test for list resources (generate_list_resource). +func (td *TemplateData) GenerateQueryTestFile(filePath string, resource api.Resource) { + templatePath := "templates/terraform/samples/base_configs/query_test_file.go.tmpl" + templates := []string{ + templatePath, + "templates/terraform/env_var_context.go.tmpl", + } + td.GenerateFile(filePath, templatePath, resource, true, templates...) +} + func (td *TemplateData) GenerateSweeperFile(filePath string, resource api.Resource) { templatePath := "templates/terraform/sweeper_file.go.tmpl" templates := []string{ diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index ef129f7e5c61..bdac82b7649d 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -113,6 +113,9 @@ func (t *Terraform) GenerateObject(object api.Resource, outputFolder, productPat t.GenerateSingularDataSourceTests(object, *templateData, outputFolder) // log.Printf("Generating %s metadata", object.Name) t.GenerateResourceMetadata(object, *templateData, outputFolder) + if object.GenerateListResource { + t.GenerateListResourceQueryTest(object, *templateData, outputFolder) + } } } @@ -259,6 +262,38 @@ func (t *Terraform) GenerateResourceTests(object api.Resource, templateData Temp templateData.GenerateTestFile(targetFilePath, object) } +// GenerateListResourceQueryTest emits resource_*_generated_query_test.go for resources with +// generate_list_resource when at least one example is eligible for tests (same rules as legacy generated tests). +func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateData TemplateData, outputFolder string) { + if object.Samples != nil && object.Examples != nil { + log.Fatalf("Both Samples and Examples block exist in %v", object.Name) + } + if object.Examples == nil { + return + } + + eligibleExample := false + for _, example := range object.Examples { + if !example.ExcludeTest { + if object.ProductMetadata.VersionObjOrClosest(t.Product.Version.Name).CompareTo(object.ProductMetadata.VersionObjOrClosest(example.MinVersion)) >= 0 { + eligibleExample = true + break + } + } + } + if !eligibleExample { + return + } + + productName := t.Product.ApiName + targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName) + if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) + } + targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s_generated_query_test.go", t.ResourceGoFilename(object))) + templateData.GenerateQueryTestFile(targetFilePath, object) +} + func (t *Terraform) GenerateResourceSweeper(object api.Resource, templateData TemplateData, outputFolder string) { if !object.ShouldGenerateSweepers() { return diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl new file mode 100644 index 000000000000..66847fc49d3c --- /dev/null +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -0,0 +1,123 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +{{$.CodeHeader TemplatePath}} + +package {{ lower $.ProductMetadata.Name }}_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + + "{{ $.ImportPath }}/acctest" + "{{ $.ImportPath }}/envvar" + "{{ $.ImportPath }}/tpgresource" +) + +var ( + _ = fmt.Sprintf + _ = strings.Trim + _ = envvar.TestEnvVar + _ = tpgresource.SetLabels +) + +{{ $example := $.FirstTestExample }} +func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { + t.Parallel() + + {{- if $example.SkipVcr }} + acctest.SkipIfVcr(t) + {{- end }} + + {{- if $example.BootstrapIam }} + acctest.BootstrapIamMembers(t, []acctest.IamMember{ + {{- range $iam := $example.BootstrapIam }} + { + Member: "{{$iam.Member}}", + Role: "{{$iam.Role}}", + }, + {{- end}} + }) + {{- end }} + + context := map[string]interface{}{ + {{- template "EnvVarContext" dict "TestEnvVars" $example.TestEnvVars "HasNewLine" false}} + {{- range $varKey, $varVal := $example.TestContextVars }} + "{{$varKey}}": {{$varVal}}, + {{- end }} + {{- range $varKey, $varVal := $example.TestVarsOverrides }} + "{{$varKey}}": {{$varVal}}, + {{- end }} + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, +{{- if $.VersionedProvider $example.MinVersion }} + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), +{{- else }} + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + {{- if $example.ExternalProviders }} + ExternalProviders: map[string]resource.ExternalProvider{ + {{- range $provider := $example.ExternalProviders }} + "{{$provider}}": {}, + {{- end }} + }, + {{- end }} +{{- end }} +{{- if not $.ExcludeDelete }} + CheckDestroy: testAccCheck{{ $.ResourceName }}DestroyProducer(t), +{{- end }} + Steps: []resource.TestStep{ + { + Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}(context), + }, +{{- if not $example.ExcludeImportTest }} + { + ResourceName: "{{ $example.ResourceType $.TerraformName }}.{{ $example.PrimaryResourceId }}", + ImportState: true, + ImportStateVerify: true, + {{- if $.IgnoreReadPropertiesToStringLegacy $example }} + ImportStateVerifyIgnore: {{ $.IgnoreReadPropertiesToStringLegacy $example }}, + {{- end }} + }, + {{- if not $.ExcludeIdentityGeneration }} + { + ResourceName: "{{ $.TerraformName }}.{{ $example.PrimaryResourceId }}", + RefreshState: true, + ExpectNonEmptyPlan: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + }, + {{- end }} +{{- end }} + { + Query: true, + Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context), + QueryResultChecks: []querycheck.QueryResultCheck{ + querycheck.ExpectLengthAtLeast("{{ $example.ResourceType $.TerraformName }}.list_query", 1), + }, + }, + }, + }) +} + +func testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context map[string]interface{}) string { + return acctest.Nprintf(` +list "{{ $example.ResourceType $.TerraformName }}" "list_query" { + provider = {{ if $.VersionedProvider $example.MinVersion }}google-beta{{ else }}google{{ end }} + config { +{{- range $scope := $.ListScopeProperties }} + {{ underscore $scope.Name }} = %({{ underscore $scope.Name }}) +{{- end }} + } +} +`, context) +} From e4097e961fbe741e1cdfe2ce16aec44e91966feb Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 21 Apr 2026 16:22:09 -0700 Subject: [PATCH 058/100] simpler flattener gen --- .../terraform/list_resource_method.go.tmpl | 26 +++++++------------ .../terraform/transport/transport.go | 6 ++--- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 5bd31c8f3edd..4e08468913c3 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -41,32 +41,26 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, BillingProject: billingProject, UserAgent: userAgent, ItemName: "{{ $.ResourceListKey }}", - Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config, _ ...string) error { + // Merge one list item into rd via Resource{{ $.ResourceName }}Flatten, then SetId. Do not set identity + // or list-scope parameters on rd here; list result identity is applied in the List() stream callback (SetResult). + Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { {{- if $.ExcludeRead }} return fmt.Errorf("list resource for {{ $.Name }} requires read support (Resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") {{- else }} - meta := interface{}(config) headers := make(http.Header) +{{- if $.HasProject }} {{- range $scope := $.ListScopeProperties }} - if {{ $scope.CamelizeProperty }} != "" { - if err := d.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { - return fmt.Errorf("error setting {{ underscore $scope.Name }} on list item temporary resource data: %w", err) - } +{{- if eq $scope.Name "project" }} + if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ $scope.CamelizeProperty }}, userAgent, billingProject, url, headers); err != nil { + return err } {{- end }} -{{- if $.HasProject }} - itemProject, err := tpgresource.GetProject(d, config) - if err != nil { - return fmt.Errorf("error fetching project for {{ $.Name }}: %w", err) - } {{- end }} - readURL, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}}{{$.SelfLinkUri}}{{$.ReadQueryParams}}") - if err != nil { - return err - } - if err := Resource{{ $.ResourceName }}Flatten(d, meta, res, config, {{- if $.HasProject }}itemProject,{{ end }} userAgent, billingProject, readURL, headers); err != nil { +{{- else }} + if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, userAgent, billingProject, url, headers); err != nil { return err } +{{- end }} id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") if err != nil { return fmt.Errorf("Error constructing id: %s", err) diff --git a/mmv1/third_party/terraform/transport/transport.go b/mmv1/third_party/terraform/transport/transport.go index f30bb3d207ac..eb2a0054c878 100644 --- a/mmv1/third_party/terraform/transport/transport.go +++ b/mmv1/third_party/terraform/transport/transport.go @@ -207,9 +207,9 @@ type ListPagesOptions struct { UserAgent string ItemName string Filter string - // Flattener maps one list JSON object onto TempData; optional trailing args reserved for callers. - Flattener func(item map[string]interface{}, d *schema.ResourceData, config *Config, args ...string) error - Callback func(rd *schema.ResourceData) error + // Flattener maps one list JSON object onto TempData. + Flattener func(item map[string]interface{}, d *schema.ResourceData, config *Config) error + Callback func(rd *schema.ResourceData) error } // ListPages performs a paginated GET request against ListURL and processes each item in the From 4e097d36d8617735ed4e402e5bbd932a105f457d Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 22 Apr 2026 15:08:26 -0700 Subject: [PATCH 059/100] add settable_propeorties that are only set on create --- .../terraform/list_resource_method.go.tmpl | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 4e08468913c3..559274a20334 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -41,8 +41,10 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, BillingProject: billingProject, UserAgent: userAgent, ItemName: "{{ $.ResourceListKey }}", - // Merge one list item into rd via Resource{{ $.ResourceName }}Flatten, then SetId. Do not set identity - // or list-scope parameters on rd here; list result identity is applied in the List() stream callback (SetResult). + // Merge one list item into rd via Resource{{ $.ResourceName }}Flatten, then SetId. list-scope + // parameters stay on temp resource data only. After Flatten (custom decoder may add keys, e.g. name from + // metadata), copy url_param/identity from res to rd for TypeInt and display name (int/string coerce). + // List() SetResult then reads rd for list result identity/DisplayName. Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { {{- if $.ExcludeRead }} return fmt.Errorf("list resource for {{ $.Name }} requires read support (Resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") @@ -60,6 +62,35 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, userAgent, billingProject, url, headers); err != nil { return err } +{{- end }} +{{- /* after decoder inside Flatten: res keys match d.Set for identity fields */ -}} +{{- range $id := $.IdentityProperties }} +{{- if $id.ApiName }} + if v, ok := res["{{ $id.ApiName }}"]; ok && v != nil { + {{- if eq $id.Type "Integer" }} + var vv interface{} + switch t := v.(type) { + case int: + vv = t + case string: + i, serr := strconv.Atoi(t) + if serr != nil { + return fmt.Errorf("Error coercing {{ underscore $id.Name }}: %s", serr) + } + vv = i + default: + return fmt.Errorf("Error coercing {{ underscore $id.Name }}: need int or string, got %T", v) + } + if err := d.Set("{{ underscore $id.Name }}", vv); err != nil { + return fmt.Errorf("Error setting {{ underscore $id.Name }}: %s", err) + } + {{- else }} + if err := d.Set("{{ underscore $id.Name }}", v); err != nil { + return fmt.Errorf("Error setting {{ underscore $id.Name }}: %s", err) + } + {{- end }} + } +{{- end }} {{- end }} id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") if err != nil { From 2ed4fd6cc4d03750d29713d29df0eab4fccb20bf Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 22 Apr 2026 16:05:03 -0700 Subject: [PATCH 060/100] remove unused existsInBaseUrl --- mmv1/google/template_utils.go | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/mmv1/google/template_utils.go b/mmv1/google/template_utils.go index 72b8392b10b1..f2b66262fe83 100644 --- a/mmv1/google/template_utils.go +++ b/mmv1/google/template_utils.go @@ -20,7 +20,6 @@ import ( "io/fs" "path/filepath" "reflect" - "regexp" "strings" "text/template" @@ -84,9 +83,8 @@ func (t functionsData) templateFunctions() template.FuncMap { "sub": subtract, "plus": plus, "firstSentence": FirstSentence, - "trimTemplate": t.trimTemplate, - "customTemplate": t.customTemplate, - "existsInBaseUrl": t.existsInBaseUrl, + "trimTemplate": t.trimTemplate, + "customTemplate": t.customTemplate, } } @@ -133,17 +131,6 @@ func (t *functionsData) trimTemplate(templatePath string, e any) (string, error) return fmt.Sprintf("%s\n", rs), nil } -// existsInBaseUrl reports whether urlTemplate contains a ReplaceVars-style token {{key}}. -func (t *functionsData) existsInBaseUrl(urlTemplate string, key string) bool { - re := regexp.MustCompile(`\{\{(\w+)\}\}`) - for _, match := range re.FindAllStringSubmatch(urlTemplate, -1) { - if len(match) > 1 && match[1] == key { - return true - } - } - return false -} - func (t functionsData) customTemplate(e any, templatePath string, appendNewline bool) (string, error) { templates := []string{ templatePath, From 5e63bc72c9c6a1cd0aed37be6d0819884e4315bc Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 09:32:53 -0700 Subject: [PATCH 061/100] simplify ResourceFlattener call in list_resource_method.go.tmpl --- .../templates/terraform/list_resource_method.go.tmpl | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 559274a20334..fcbc154b6a6b 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -50,19 +50,9 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return fmt.Errorf("list resource for {{ $.Name }} requires read support (Resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") {{- else }} headers := make(http.Header) -{{- if $.HasProject }} -{{- range $scope := $.ListScopeProperties }} -{{- if eq $scope.Name "project" }} - if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ $scope.CamelizeProperty }}, userAgent, billingProject, url, headers); err != nil { +if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { return err } -{{- end }} -{{- end }} -{{- else }} - if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, userAgent, billingProject, url, headers); err != nil { - return err - } -{{- end }} {{- /* after decoder inside Flatten: res keys match d.Set for identity fields */ -}} {{- range $id := $.IdentityProperties }} {{- if $id.ApiName }} From e17679bdb2a8fe264c2a1a6d9247b15a6cd2aefa Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 11:55:33 -0700 Subject: [PATCH 062/100] remove comments --- mmv1/templates/terraform/list_resource_method.go.tmpl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index fcbc154b6a6b..904df11fd019 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -6,8 +6,6 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, callback func(*schema.ResourceData) error, ) error { resourceData := Resource{{ $.ResourceName }}().Data(&terraform.InstanceState{}) - // ReplaceVars expands {{"{{"}}{{$.ProductMetadata.Name}}BasePath{{"}}"}} (product base_url) and base_url using resourceData. - // Set every resolved list scope parameter on resourceData before building the list URL. {{- range $scope := $.ListScopeProperties }} if {{ $scope.CamelizeProperty }} != "" { if err := resourceData.Set("{{ underscore $scope.Name }}", {{ $scope.CamelizeProperty }}); err != nil { @@ -41,10 +39,6 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, BillingProject: billingProject, UserAgent: userAgent, ItemName: "{{ $.ResourceListKey }}", - // Merge one list item into rd via Resource{{ $.ResourceName }}Flatten, then SetId. list-scope - // parameters stay on temp resource data only. After Flatten (custom decoder may add keys, e.g. name from - // metadata), copy url_param/identity from res to rd for TypeInt and display name (int/string coerce). - // List() SetResult then reads rd for list result identity/DisplayName. Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { {{- if $.ExcludeRead }} return fmt.Errorf("list resource for {{ $.Name }} requires read support (Resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") From 85b0e9cf0273bbc958354436a8f6f486bca31e63 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 12:21:47 -0700 Subject: [PATCH 063/100] simplify case where the res can be a TypeInt but res returns string --- .../terraform/list_resource_method.go.tmpl | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 904df11fd019..7d2a0c3013fe 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -47,32 +47,22 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { return err } -{{- /* after decoder inside Flatten: res keys match d.Set for identity fields */ -}} +{{- /* url_param_only identity fields (e.g. name) are not GettableProperties, so the flattener does not Set them. Copy from res → d here so SetId/ListResultDisplayName can find them. Integer ids sometimes arrive as strings and need coercion. */ -}} {{- range $id := $.IdentityProperties }} {{- if $id.ApiName }} if v, ok := res["{{ $id.ApiName }}"]; ok && v != nil { {{- if eq $id.Type "Integer" }} - var vv interface{} - switch t := v.(type) { - case int: - vv = t - case string: - i, serr := strconv.Atoi(t) - if serr != nil { - return fmt.Errorf("Error coercing {{ underscore $id.Name }}: %s", serr) + if s, ok := v.(string); ok { + i, err := strconv.Atoi(s) + if err != nil { + return fmt.Errorf("Error coercing {{ underscore $id.Name }}: %s", err) } - vv = i - default: - return fmt.Errorf("Error coercing {{ underscore $id.Name }}: need int or string, got %T", v) + v = i } - if err := d.Set("{{ underscore $id.Name }}", vv); err != nil { - return fmt.Errorf("Error setting {{ underscore $id.Name }}: %s", err) - } - {{- else }} + {{- end }} if err := d.Set("{{ underscore $id.Name }}", v); err != nil { return fmt.Errorf("Error setting {{ underscore $id.Name }}: %s", err) } - {{- end }} } {{- end }} {{- end }} From 52af40ca70c11a82c9ccd08f331e771f8c10e7d6 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 12:39:20 -0700 Subject: [PATCH 064/100] simplify getGeneratedListResoucesInVersion --- mmv1/provider/terraform.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index bdac82b7649d..3109620bbc2c 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -1109,16 +1109,7 @@ func (t Terraform) GetGeneratedListResourcesInVersion(products []*api.Product) [ var out []GeneratedListResourceRegistration for _, productDefinition := range products { for _, object := range productDefinition.Objects { - if object.Exclude || object.NotInVersion(productDefinition.VersionObjOrClosest(t.TargetVersionName)) { - continue - } - if object.IsExcluded() { - continue - } - if !object.GenerateListResource { - continue - } - if object.ExcludeIdentityGeneration { + if object.NotInVersion(productDefinition.VersionObjOrClosest(t.TargetVersionName)) || object.IsExcluded() || !object.GenerateListResource { continue } out = append(out, GeneratedListResourceRegistration{ From dccd3be3f14dcaac058ccdcc447b31c43727e511 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 12:54:14 -0700 Subject: [PATCH 065/100] more robust ListResultDsiplayNameKeyStrings method --- mmv1/api/resource.go | 27 +++++++++---------- .../terraform/tpgresource/list_resource.go | 15 +++++------ 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 4b75258b4b77..11a5bc9594a7 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -248,11 +248,6 @@ type Resource struct { // If true, generate a list resource for the resource GenerateListResource bool `yaml:"generate_list_resource,omitempty"` - // ListResultDisplayNameKeys lists Terraform schema attribute names (snake_case), in priority order, - // passed to tpgresource.ListResourceMetadata.SetResult as displayNameKeys. Used when - // generate_list_resource is true. If empty, default is ["name"] when a root "name" property exists. - ListResultDisplayNameKeys []string `yaml:"list_result_display_name_keys,omitempty"` - // If true, skip sweeper generation for this resource ExcludeSweeper bool `yaml:"exclude_sweeper,omitempty"` @@ -740,19 +735,23 @@ func (r Resource) ListScopeProperties() []*Type { return props } -// ListResultDisplayNameKeyStrings returns Terraform attribute names for list result DisplayName -// (SetResult variadic args). YAML list_result_display_name_keys overrides; otherwise ["name"] -// when a root user property "name" exists. +// ListResultDisplayNameKeyStrings returns Terraform attribute names passed to +// tpgresource.ListResourceMetadata.SetResult as displayNameKeys, in priority order: +// a root "display_name" property (if present), then the terminal identifier from +// IdFormat (e.g. "name", "disk_id", "instance_id"). func (r Resource) ListResultDisplayNameKeyStrings() []string { - if len(r.ListResultDisplayNameKeys) > 0 { - return r.ListResultDisplayNameKeys - } + var keys []string for _, p := range r.RootProperties() { - if p.Name == "name" { - return []string{"name"} + if p.Name == "display_name" { + keys = append(keys, "display_name") + break } } - return nil + markers := regexp.MustCompile(`\{\{(\w+)\}\}`).FindAllStringSubmatch(r.IdFormat, -1) + if len(markers) > 0 { + keys = append(keys, markers[len(markers)-1][1]) + } + return keys } func (r Resource) SensitiveProps() []*Type { diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index 2dec34b042aa..de32022e90b5 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -191,7 +191,7 @@ func (listR *ListResourceMetadata) setResourceIdentity(rd *schema.ResourceData) // ListResultDisplayName returns the first non-empty label from rd for keys in order. Use a // single key or several for fallbacks (e.g. display_name then email). -// it returns an error if none of the keys yield a non-empty string. +// It returns an error if none of the keys yield a non-empty string. func ListResultDisplayName(rd *schema.ResourceData, keys ...string) (string, error) { if rd == nil { return "", fmt.Errorf("ListResultDisplayName: ResourceData is nil") @@ -200,12 +200,10 @@ func ListResultDisplayName(rd *schema.ResourceData, keys ...string) (string, err return "", fmt.Errorf("ListResultDisplayName: no keys provided") } for _, k := range keys { - v, ok := rd.GetOk(k) - if !ok { - continue - } - if s := fmt.Sprintf("%v", v); s != "" { - return s, nil + if v, ok := rd.GetOk(k); ok { + if s := fmt.Sprintf("%v", v); s != "" { + return s, nil + } } } return "", fmt.Errorf("ListResultDisplayName: no non-empty value among keys %q", keys) @@ -213,8 +211,7 @@ func ListResultDisplayName(rd *schema.ResourceData, keys ...string) (string, err // SetResult fills list result identity from rd; if includeResource, also full resource state. // displayNameKeys lists schema attribute names (in priority order) used to set result.DisplayName -// via ListResultDisplayName when it is still empty; omit or pass no keys to skip. Non-empty keys -// produce an error if no key yields a non-empty display label. +// via ListResultDisplayName when it is still empty; omit or pass no keys to skip. func (listR *ListResourceMetadata) SetResult(ctx context.Context, includeResource bool, result *list.ListResult, rd *schema.ResourceData, displayNameKeys ...string) error { if err := listR.setResourceIdentity(rd); err != nil { return err From dd97142d41f330157a27a7ac42b5a81de43d0d20 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 12:58:47 -0700 Subject: [PATCH 066/100] simplify ListScopeProperties --- mmv1/api/resource.go | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 11a5bc9594a7..bcb264e73e23 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -245,13 +245,12 @@ type Resource struct { // EXPERIMENTAL: If true, resource should be autogenerated as a data source Datasource *resource.Datasource `yaml:"datasource_experimental,omitempty"` - // If true, generate a list resource for the resource GenerateListResource bool `yaml:"generate_list_resource,omitempty"` // If true, skip sweeper generation for this resource ExcludeSweeper bool `yaml:"exclude_sweeper,omitempty"` - // If true, skip identity generation for this resource. Incompatible with generate_list_resource. + // If true, skip identity generation for this resource ExcludeIdentityGeneration bool `yaml:"exclude_identity_generation,omitempty"` // Override sweeper settings @@ -718,21 +717,15 @@ func (r Resource) IdentityProperties() []*Type { return props } -// ListScopeProperties returns the subset of IdentityProperties whose -// template variable (e.g. {{project}}) appears in the full collection URL -// (product base_url + resource base_url). These are the scoping parameters -// a practitioner must supply for a list call — not the resource's own -// identifier like "name". +// ListScopeProperties returns the subset of IdentityProperties whose identifier +// appears in the collection URL (product base_url + resource base_url). These are +// the scoping parameters a practitioner must supply for a list call — not the +// resource's own identifier like "name". func (r Resource) ListScopeProperties() []*Type { - collectionUrl := r.CollectionUrl() - var props []*Type - for _, p := range r.IdentityProperties() { - varName := "{{" + google.Underscore(p.Name) + "}}" - if strings.Contains(collectionUrl, varName) { - props = append(props, p) - } - } - return props + scope := r.ExtractIdentifiers(r.CollectionUrl()) + return google.Select(r.IdentityProperties(), func(p *Type) bool { + return slices.Contains(scope, google.Underscore(p.Name)) + }) } // ListResultDisplayNameKeyStrings returns Terraform attribute names passed to From a782d735ad80d2d67d77398b44b2648b8b855d55 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 13:05:07 -0700 Subject: [PATCH 067/100] remove HasLocation method --- mmv1/api/resource.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index bcb264e73e23..67cc8a2a10b3 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -1346,13 +1346,6 @@ func (r Resource) HasZone() bool { return found && strings.Contains(r.BaseUrl, "{{zone}}") } -// HasLocation is true when URLs use a {{location}} segment (e.g. Cloud Run, Cloud Functions). -func (r Resource) HasLocation() bool { - return strings.Contains(r.BaseUrl, "{{location}}") || - strings.Contains(r.CreateUrl, "{{location}}") || - strings.Contains(r.SelfLinkUri(), "{{location}}") -} - // resource functions needed for template that previously existed in terraform.go // but due to how files are being inherited here it was easier to put in here // taken wholesale from tpgtools From 3c19d8e97856f078c757e1e05de3eab729ae68d3 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 13:06:55 -0700 Subject: [PATCH 068/100] cleanup service.yaml --- mmv1/products/cloudrun/Service.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 672b1601c5a8..bcef9c624663 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -32,14 +32,9 @@ import_format: - 'locations/{{location}}/namespaces/{{project}}/services/{{name}}' datasource_experimental: generate: true - # plural: - # generate: true - # list_function: 'templates/terraform/list_functions/cloud_run_service.go.tmpl' exclude_test: true generate_list_resource: true -# Knative-style list responses use "items" (not the default "services" key). -collection_url_key: 'items' timeouts: insert_minutes: 20 update_minutes: 20 From cdf96f8d14cc51e5391d6cf9463e69f540607b33 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 13:08:33 -0700 Subject: [PATCH 069/100] more --- mmv1/third_party/terraform/transport/transport.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/transport/transport.go b/mmv1/third_party/terraform/transport/transport.go index eb2a0054c878..d6dae5f69c6c 100644 --- a/mmv1/third_party/terraform/transport/transport.go +++ b/mmv1/third_party/terraform/transport/transport.go @@ -207,9 +207,8 @@ type ListPagesOptions struct { UserAgent string ItemName string Filter string - // Flattener maps one list JSON object onto TempData. - Flattener func(item map[string]interface{}, d *schema.ResourceData, config *Config) error - Callback func(rd *schema.ResourceData) error + Flattener func(item map[string]interface{}, d *schema.ResourceData, config *Config) error + Callback func(rd *schema.ResourceData) error } // ListPages performs a paginated GET request against ListURL and processes each item in the From 3e46864c46250baa4191f0323b2126aaba53efec Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 13:54:25 -0700 Subject: [PATCH 070/100] refactors in templates --- mmv1/products/cloudrun/Service.yaml | 2 +- mmv1/provider/terraform.go | 3 +++ mmv1/templates/terraform/list_resource.go.tmpl | 1 - .../terraform/list_resource_method.go.tmpl | 14 +++++--------- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index bcef9c624663..2c81fc9e4283 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -33,8 +33,8 @@ import_format: datasource_experimental: generate: true exclude_test: true - generate_list_resource: true +collection_url_key: 'items' timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 3109620bbc2c..cad82be3424c 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -162,6 +162,9 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD if object.ExcludeIdentityGeneration { log.Fatalf("generate_list_resource requires identity support; remove exclude_identity_generation from resource %q or disable generate_list_resource", object.Name) } + if object.ExcludeRead { + log.Fatalf("generate_list_resource requires read support; remove exclude_read from resource %q or disable generate_list_resource", object.Name) + } targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_resource_%s.go", t.ResourceGoFilename(object))) templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, "templates/terraform/list_resource.go.tmpl", diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index d81819c7325a..70dde5b5ccd8 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -24,7 +24,6 @@ import ( "errors" "fmt" "net/http" - "regexp" {{- if and $.HasProject $.LegacyLongFormProject }} "strings" {{- end }} diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 7d2a0c3013fe..a8480b9fa7cd 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -20,9 +20,9 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, } billingProject := "" - if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { - billingProject = parts[1] - } +{{- if $.HasProject }} + billingProject = project +{{- end }} if bp, err := tpgresource.GetBillingProject(resourceData, config); err == nil { billingProject = bp } @@ -38,13 +38,10 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, ListURL: url, BillingProject: billingProject, UserAgent: userAgent, - ItemName: "{{ $.ResourceListKey }}", + ItemName: "{{ $.CollectionUrlKey }}", Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { -{{- if $.ExcludeRead }} - return fmt.Errorf("list resource for {{ $.Name }} requires read support (Resource{{ $.ResourceName }}Flatten is not generated when exclude_read is set)") -{{- else }} headers := make(http.Header) -if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { + if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { return err } {{- /* url_param_only identity fields (e.g. name) are not GettableProperties, so the flattener does not Set them. Copy from res → d here so SetId/ListResultDisplayName can find them. Integer ids sometimes arrive as strings and need coercion. */ -}} @@ -72,7 +69,6 @@ if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasPr } d.SetId(id) return nil -{{- end }} }, Callback: callback, }) From 01bc236c43b3f7646aef7c4a4383bbfbfb61b395 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 14:07:55 -0700 Subject: [PATCH 071/100] simplify query_test_gen --- .../base_configs/query_test_file.go.tmpl | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index 66847fc49d3c..430bd197bef4 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -6,8 +6,6 @@ package {{ lower $.ProductMetadata.Name }}_test import ( - "fmt" - "strings" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -16,14 +14,10 @@ import ( "{{ $.ImportPath }}/acctest" "{{ $.ImportPath }}/envvar" - "{{ $.ImportPath }}/tpgresource" ) var ( - _ = fmt.Sprintf - _ = strings.Trim _ = envvar.TestEnvVar - _ = tpgresource.SetLabels ) {{ $example := $.FirstTestExample }} @@ -45,6 +39,7 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { }) {{- end }} + randomSuffix := acctest.RandString(t, 10) context := map[string]interface{}{ {{- template "EnvVarContext" dict "TestEnvVars" $example.TestEnvVars "HasNewLine" false}} {{- range $varKey, $varVal := $example.TestContextVars }} @@ -53,7 +48,7 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { {{- range $varKey, $varVal := $example.TestVarsOverrides }} "{{$varKey}}": {{$varVal}}, {{- end }} - "random_suffix": acctest.RandString(t, 10), + "random_suffix": randomSuffix, } acctest.VcrTest(t, resource.TestCase{ @@ -80,24 +75,6 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { { Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}(context), }, -{{- if not $example.ExcludeImportTest }} - { - ResourceName: "{{ $example.ResourceType $.TerraformName }}.{{ $example.PrimaryResourceId }}", - ImportState: true, - ImportStateVerify: true, - {{- if $.IgnoreReadPropertiesToStringLegacy $example }} - ImportStateVerifyIgnore: {{ $.IgnoreReadPropertiesToStringLegacy $example }}, - {{- end }} - }, - {{- if not $.ExcludeIdentityGeneration }} - { - ResourceName: "{{ $.TerraformName }}.{{ $example.PrimaryResourceId }}", - RefreshState: true, - ExpectNonEmptyPlan: true, - ImportStateKind: resource.ImportBlockWithResourceIdentity, - }, - {{- end }} -{{- end }} { Query: true, Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context), From 7f61926d1bc22992e55d2e2d99a754b5063e6454 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 14:31:32 -0700 Subject: [PATCH 072/100] fixes on query test gen + passing run for cloudrun service query --- .../samples/base_configs/query_test_file.go.tmpl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index 430bd197bef4..ec869700ed39 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -47,6 +47,14 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { {{- end }} {{- range $varKey, $varVal := $example.TestVarsOverrides }} "{{$varKey}}": {{$varVal}}, + {{- end }} + {{- range $scope := $.ListScopeProperties }} + {{- $n := underscore $scope.Name }} + {{- if or (eq $n "region") (eq $n "location") }} + "{{$n}}": envvar.GetTestRegionFromEnv(), + {{- else if eq $n "zone" }} + "zone": envvar.GetTestZoneFromEnv(), + {{- end }} {{- end }} "random_suffix": randomSuffix, } @@ -92,7 +100,7 @@ list "{{ $example.ResourceType $.TerraformName }}" "list_query" { provider = {{ if $.VersionedProvider $example.MinVersion }}google-beta{{ else }}google{{ end }} config { {{- range $scope := $.ListScopeProperties }} - {{ underscore $scope.Name }} = %({{ underscore $scope.Name }}) + {{ underscore $scope.Name }} = "%{{"{"}}{{ underscore $scope.Name }}{{"}"}}" {{- end }} } } From d5947ad9b95743abd2646aab9c9c7002e3ed311e Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 14:33:46 -0700 Subject: [PATCH 073/100] revert refactor --- .../terraform/tpgresource/list_resource.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index de32022e90b5..4aa938e4ee20 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -191,7 +191,7 @@ func (listR *ListResourceMetadata) setResourceIdentity(rd *schema.ResourceData) // ListResultDisplayName returns the first non-empty label from rd for keys in order. Use a // single key or several for fallbacks (e.g. display_name then email). -// It returns an error if none of the keys yield a non-empty string. +// it returns an error if none of the keys yield a non-empty string. func ListResultDisplayName(rd *schema.ResourceData, keys ...string) (string, error) { if rd == nil { return "", fmt.Errorf("ListResultDisplayName: ResourceData is nil") @@ -200,10 +200,12 @@ func ListResultDisplayName(rd *schema.ResourceData, keys ...string) (string, err return "", fmt.Errorf("ListResultDisplayName: no keys provided") } for _, k := range keys { - if v, ok := rd.GetOk(k); ok { - if s := fmt.Sprintf("%v", v); s != "" { - return s, nil - } + v, ok := rd.GetOk(k) + if !ok { + continue + } + if s := fmt.Sprintf("%v", v); s != "" { + return s, nil } } return "", fmt.Errorf("ListResultDisplayName: no non-empty value among keys %q", keys) From 29a93a4915d638bf8b642091045821b6e7f21a8a Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 14:35:54 -0700 Subject: [PATCH 074/100] remove more --- mmv1/api/resource.go | 8 -------- mmv1/provider/terraform.go | 5 ----- mmv1/third_party/terraform/tpgresource/list_resource.go | 3 ++- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 67cc8a2a10b3..370eb3df3583 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -717,10 +717,6 @@ func (r Resource) IdentityProperties() []*Type { return props } -// ListScopeProperties returns the subset of IdentityProperties whose identifier -// appears in the collection URL (product base_url + resource base_url). These are -// the scoping parameters a practitioner must supply for a list call — not the -// resource's own identifier like "name". func (r Resource) ListScopeProperties() []*Type { scope := r.ExtractIdentifiers(r.CollectionUrl()) return google.Select(r.IdentityProperties(), func(p *Type) bool { @@ -728,10 +724,6 @@ func (r Resource) ListScopeProperties() []*Type { }) } -// ListResultDisplayNameKeyStrings returns Terraform attribute names passed to -// tpgresource.ListResourceMetadata.SetResult as displayNameKeys, in priority order: -// a root "display_name" property (if present), then the terminal identifier from -// IdFormat (e.g. "name", "disk_id", "instance_id"). func (r Resource) ListResultDisplayNameKeyStrings() []string { var keys []string for _, p := range r.RootProperties() { diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index cad82be3424c..d13ba5784fed 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -265,8 +265,6 @@ func (t *Terraform) GenerateResourceTests(object api.Resource, templateData Temp templateData.GenerateTestFile(targetFilePath, object) } -// GenerateListResourceQueryTest emits resource_*_generated_query_test.go for resources with -// generate_list_resource when at least one example is eligible for tests (same rules as legacy generated tests). func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateData TemplateData, outputFolder string) { if object.Samples != nil && object.Examples != nil { log.Fatalf("Both Samples and Examples block exist in %v", object.Name) @@ -1106,8 +1104,6 @@ type GeneratedListResourceRegistration struct { NewFunc string // e.g. "NewCloudRunServiceListResource" } -// GetGeneratedListResourcesInVersion returns list-resource registrations for all products -// in the same order as list_resource_*.go generation (version, exclude, generate_list_resource). func (t Terraform) GetGeneratedListResourcesInVersion(products []*api.Product) []GeneratedListResourceRegistration { var out []GeneratedListResourceRegistration for _, productDefinition := range products { @@ -1130,7 +1126,6 @@ func (t Terraform) GetGeneratedListResourcesInVersion(products []*api.Product) [ return out } -// GetListResourceImportPackages returns sorted unique service import paths for generated list resources. func (t Terraform) GetListResourceImportPackages(products []*api.Product) []string { reg := t.GetGeneratedListResourcesInVersion(products) seen := make(map[string]struct{}, len(reg)) diff --git a/mmv1/third_party/terraform/tpgresource/list_resource.go b/mmv1/third_party/terraform/tpgresource/list_resource.go index 4aa938e4ee20..2dec34b042aa 100644 --- a/mmv1/third_party/terraform/tpgresource/list_resource.go +++ b/mmv1/third_party/terraform/tpgresource/list_resource.go @@ -213,7 +213,8 @@ func ListResultDisplayName(rd *schema.ResourceData, keys ...string) (string, err // SetResult fills list result identity from rd; if includeResource, also full resource state. // displayNameKeys lists schema attribute names (in priority order) used to set result.DisplayName -// via ListResultDisplayName when it is still empty; omit or pass no keys to skip. +// via ListResultDisplayName when it is still empty; omit or pass no keys to skip. Non-empty keys +// produce an error if no key yields a non-empty display label. func (listR *ListResourceMetadata) SetResult(ctx context.Context, includeResource bool, result *list.ListResult, rd *schema.ResourceData, displayNameKeys ...string) error { if err := listR.setResourceIdentity(rd); err != nil { return err From 4ae54caff71245503d34d2e469353cd00133ac47 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 14:59:42 -0700 Subject: [PATCH 075/100] improved testing on ResourceDisplayName --- .../samples/base_configs/query_test_file.go.tmpl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index ec869700ed39..560393a44019 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -6,10 +6,13 @@ package {{ lower $.ProductMetadata.Name }}_test import ( + "regexp" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/querycheck/queryfilter" "github.com/hashicorp/terraform-plugin-testing/tfversion" "{{ $.ImportPath }}/acctest" @@ -88,6 +91,11 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context), QueryResultChecks: []querycheck.QueryResultCheck{ querycheck.ExpectLengthAtLeast("{{ $example.ResourceType $.TerraformName }}.list_query", 1), + querycheck.ExpectResourceDisplayName( + "{{ $example.ResourceType $.TerraformName }}.list_query", + queryfilter.ByDisplayName(knownvalue.StringRegexp(regexp.MustCompile(randomSuffix+`$`))), + knownvalue.StringRegexp(regexp.MustCompile(randomSuffix+`$`)), + ), }, }, }, From 67f2b06fbcbea8796165a9d3b5d40823406ade93 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 23 Apr 2026 15:05:04 -0700 Subject: [PATCH 076/100] rename of generated files for list --- mmv1/provider/terraform.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index d13ba5784fed..f47916f3827b 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -165,7 +165,7 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD if object.ExcludeRead { log.Fatalf("generate_list_resource requires read support; remove exclude_read from resource %q or disable generate_list_resource", object.Name) } - targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_resource_%s.go", t.ResourceGoFilename(object))) + targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s.go", t.ResourceGoFilename(object))) templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, "templates/terraform/list_resource.go.tmpl", "templates/terraform/list_resource_method.go.tmpl", @@ -291,7 +291,7 @@ func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateD if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) } - targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s_generated_query_test.go", t.ResourceGoFilename(object))) + targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s_generated_test.go", t.ResourceGoFilename(object))) templateData.GenerateQueryTestFile(targetFilePath, object) } From 6fb51c7ed2930ee35c9280f87d476127ad96aa79 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 27 Apr 2026 14:18:01 -0700 Subject: [PATCH 077/100] move Decoder, NestedQuery, and PostRead in list_resource__method.go.tmpl --- .../terraform/list_resource_method.go.tmpl | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index a8480b9fa7cd..13574570b26c 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -41,6 +41,34 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, ItemName: "{{ $.CollectionUrlKey }}", Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { headers := make(http.Header) +{{- if or $.CustomCode.PostRead $.NestedQuery $.CustomCode.Decoder }} + var meta interface{} = config + _ = meta +{{- end }} +{{- if or $.NestedQuery $.CustomCode.Decoder }} + var err error +{{- end }} +{{- if $.CustomCode.PostRead }} + {{ customTemplate $ $.CustomCode.PostRead false -}} +{{- end }} +{{- if $.NestedQuery }} + res, err = flattenNested{{ $.ResourceName -}}(d, meta, res) + if err != nil { + return err + } + if res == nil { + return fmt.Errorf("Error matching nested {{ $.ResourceName }} from list response") + } +{{- end }} +{{- if $.CustomCode.Decoder }} + res, err = resource{{ $.ResourceName -}}Decoder(d, meta, res) + if err != nil { + return err + } + if res == nil { + return fmt.Errorf("Error decoding {{ $.ResourceName }} from list response") + } +{{- end }} if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { return err } From 2bff1caccbb8e68b51fde5005486b4b7c20b44e9 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 27 Apr 2026 16:10:06 -0700 Subject: [PATCH 078/100] use bootstrapProjects for query_test generation --- mmv1/products/cloudbuild/Trigger.yaml | 2 ++ .../samples/base_configs/query_test_file.go.tmpl | 10 ++-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/mmv1/products/cloudbuild/Trigger.yaml b/mmv1/products/cloudbuild/Trigger.yaml index a4a37123c1da..3402ac8c85d2 100644 --- a/mmv1/products/cloudbuild/Trigger.yaml +++ b/mmv1/products/cloudbuild/Trigger.yaml @@ -14,6 +14,7 @@ --- name: 'Trigger' api_resource_type_kind: BuildTrigger +collection_url_key: 'triggers' api_variant_patterns: - 'projects/{project}/locations/{location}/triggers/{trigger}' description: | @@ -38,6 +39,7 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 +generate_list_resource: true custom_code: constants: 'templates/terraform/constants/cloudbuild_trigger.tmpl' post_create: 'templates/terraform/post_create/cloudbuild_trigger_id.go.tmpl' diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index 560393a44019..df7664fc681a 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -6,13 +6,10 @@ package {{ lower $.ProductMetadata.Name }}_test import ( - "regexp" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/querycheck" - "github.com/hashicorp/terraform-plugin-testing/querycheck/queryfilter" "github.com/hashicorp/terraform-plugin-testing/tfversion" "{{ $.ImportPath }}/acctest" @@ -57,6 +54,8 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { "{{$n}}": envvar.GetTestRegionFromEnv(), {{- else if eq $n "zone" }} "zone": envvar.GetTestZoneFromEnv(), + {{- else if eq $n "project" }} + "project": acctest.BootstrapProject(t, "tf-bt-list-", envvar.GetTestBillingAccountFromEnv(t), nil).ProjectId, {{- end }} {{- end }} "random_suffix": randomSuffix, @@ -91,11 +90,6 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context), QueryResultChecks: []querycheck.QueryResultCheck{ querycheck.ExpectLengthAtLeast("{{ $example.ResourceType $.TerraformName }}.list_query", 1), - querycheck.ExpectResourceDisplayName( - "{{ $example.ResourceType $.TerraformName }}.list_query", - queryfilter.ByDisplayName(knownvalue.StringRegexp(regexp.MustCompile(randomSuffix+`$`))), - knownvalue.StringRegexp(regexp.MustCompile(randomSuffix+`$`)), - ), }, }, }, From 7f2908331349368d087bd75989d2328b025015c5 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 27 Apr 2026 17:29:24 -0700 Subject: [PATCH 079/100] add list_query_test_utils for explicit checking of DisplayName for provisioned resource --- .../base_configs/query_test_file.go.tmpl | 19 +++++++ .../acctest/list_query_test_utils.go | 49 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 mmv1/third_party/terraform/acctest/list_query_test_utils.go diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index df7664fc681a..dc06b78c6f1b 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/querycheck/queryfilter" "github.com/hashicorp/terraform-plugin-testing/tfversion" "{{ $.ImportPath }}/acctest" @@ -61,6 +62,9 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { "random_suffix": randomSuffix, } + // Captured at create-step time and asserted against list-query results. + var capturedDisplayName acctest.CapturedDisplayName + acctest.VcrTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBelow(tfversion.Version1_14_0), @@ -84,12 +88,27 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { Steps: []resource.TestStep{ { Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}(context), + Check: resource.ComposeTestCheckFunc( + capturedDisplayName.CaptureCheck( + "{{ $example.ResourceType $.TerraformName }}.{{ $example.PrimaryResourceId }}", + []string{ + {{- range $key := $.ListResultDisplayNameKeyStrings }} + "{{ $key }}", + {{- end }} + }, + ), + ), }, { Query: true, Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context), QueryResultChecks: []querycheck.QueryResultCheck{ querycheck.ExpectLengthAtLeast("{{ $example.ResourceType $.TerraformName }}.list_query", 1), + querycheck.ExpectResourceDisplayName( + "{{ $example.ResourceType $.TerraformName }}.list_query", + queryfilter.ByDisplayName(capturedDisplayName.ExpectKnownValue()), + capturedDisplayName.ExpectKnownValue(), + ), }, }, }, diff --git a/mmv1/third_party/terraform/acctest/list_query_test_utils.go b/mmv1/third_party/terraform/acctest/list_query_test_utils.go new file mode 100644 index 000000000000..848f2574d7dc --- /dev/null +++ b/mmv1/third_party/terraform/acctest/list_query_test_utils.go @@ -0,0 +1,49 @@ +package acctest + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +// CapturedDisplayName captures a resource's display-name attribute during a +// create step and exposes a knownvalue.Check that asserts list-query results +// match the captured value. +type CapturedDisplayName struct { + value string +} + +// CaptureCheck returns a TestCheckFunc that copies the first non-empty value +// among attrCandidates from resourceAddr's state into the captured value. +// attrCandidates are checked in order from first index to last. +func (c *CapturedDisplayName) CaptureCheck(resourceAddr string, attrCandidates []string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceAddr] + if !ok { + return fmt.Errorf("resource not found in state: %s", resourceAddr) + } + for _, k := range attrCandidates { + if v, ok := rs.Primary.Attributes[k]; ok && v != "" { + c.value = v + return nil + } + } + return fmt.Errorf("no display name attribute found in state for resource %s; tried %v", resourceAddr, attrCandidates) + } +} + +// ExpectKnownValue returns a knownvalue.Check that compares against the +// captured value. Fails if CaptureCheck has not run yet. +func (c *CapturedDisplayName) ExpectKnownValue() knownvalue.Check { + return knownvalue.StringFunc(func(v string) error { + if c.value == "" { + return fmt.Errorf("display name was not captured from create step") + } + if v != c.value { + return fmt.Errorf("expected display name %q, got %q", c.value, v) + } + return nil + }) +} From 02bd1f7bf55ac770f4a420c18d10bb047ee99072 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 29 Apr 2026 16:28:25 -0700 Subject: [PATCH 080/100] move list test utils to test_utils.go.tmpl --- .../acctest/list_query_test_utils.go | 49 ------------------- .../list_google_service_account_test.go | 5 +- 2 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 mmv1/third_party/terraform/acctest/list_query_test_utils.go diff --git a/mmv1/third_party/terraform/acctest/list_query_test_utils.go b/mmv1/third_party/terraform/acctest/list_query_test_utils.go deleted file mode 100644 index 848f2574d7dc..000000000000 --- a/mmv1/third_party/terraform/acctest/list_query_test_utils.go +++ /dev/null @@ -1,49 +0,0 @@ -package acctest - -import ( - "fmt" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/knownvalue" - "github.com/hashicorp/terraform-plugin-testing/terraform" -) - -// CapturedDisplayName captures a resource's display-name attribute during a -// create step and exposes a knownvalue.Check that asserts list-query results -// match the captured value. -type CapturedDisplayName struct { - value string -} - -// CaptureCheck returns a TestCheckFunc that copies the first non-empty value -// among attrCandidates from resourceAddr's state into the captured value. -// attrCandidates are checked in order from first index to last. -func (c *CapturedDisplayName) CaptureCheck(resourceAddr string, attrCandidates []string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceAddr] - if !ok { - return fmt.Errorf("resource not found in state: %s", resourceAddr) - } - for _, k := range attrCandidates { - if v, ok := rs.Primary.Attributes[k]; ok && v != "" { - c.value = v - return nil - } - } - return fmt.Errorf("no display name attribute found in state for resource %s; tried %v", resourceAddr, attrCandidates) - } -} - -// ExpectKnownValue returns a knownvalue.Check that compares against the -// captured value. Fails if CaptureCheck has not run yet. -func (c *CapturedDisplayName) ExpectKnownValue() knownvalue.Check { - return knownvalue.StringFunc(func(v string) error { - if c.value == "" { - return fmt.Errorf("display name was not captured from create step") - } - if v != c.value { - return fmt.Errorf("expected display name %q, got %q", c.value, v) - } - return nil - }) -} diff --git a/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go b/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go index f9dca1d8cf7c..80e33254ad1f 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go @@ -23,7 +23,8 @@ func TestAccServiceAccountListResource_queryIdentity(t *testing.T) { accountId := "a" + acctest.RandString(t, 10) project := envvar.GetTestProjectFromEnv() expectedEmail := fmt.Sprintf("%s@%s.iam.gserviceaccount.com", accountId, project) - listDisplayName := acctest.ListDisplayName{} + var listDisplayName = acctest.ListDisplayName{} + acctest.VcrTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBelow(tfversion.Version1_14_0), @@ -36,7 +37,7 @@ func TestAccServiceAccountListResource_queryIdentity(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("google_service_account.acceptance", "email", expectedEmail), resource.TestCheckResourceAttr("google_service_account.acceptance", "project", project), - listDisplayName.Capture("google_service_account.acceptance", []string{"display_name", "email"}), + listDisplayName.Capture("google_service_account.acceptance", []string{"display_name"}), ), }, { From 3468e8c4ade1a01abe56cb07760cd8324aee4256 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 29 Apr 2026 17:24:33 -0700 Subject: [PATCH 081/100] storage bucket testing + refining testing for non variable update --- mmv1/products/storage/Folder.yaml | 1 + .../samples/base_configs/query_test_file.go.tmpl | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mmv1/products/storage/Folder.yaml b/mmv1/products/storage/Folder.yaml index c2cc0b9da102..881876ee84d4 100644 --- a/mmv1/products/storage/Folder.yaml +++ b/mmv1/products/storage/Folder.yaml @@ -24,6 +24,7 @@ timeouts: update_minutes: 20 delete_minutes: 20 exclude_sweeper: true +generate_list_resource: true import_format: - '{{bucket}}/folders/{{%name}}' - '{{bucket}}/{{%name}}' diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index dc06b78c6f1b..2f3e56ecc36b 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -63,7 +63,7 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { } // Captured at create-step time and asserted against list-query results. - var capturedDisplayName acctest.CapturedDisplayName + var listDisplayName acctest.ListDisplayName acctest.VcrTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ @@ -89,7 +89,7 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { { Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}(context), Check: resource.ComposeTestCheckFunc( - capturedDisplayName.CaptureCheck( + listDisplayName.Capture( "{{ $example.ResourceType $.TerraformName }}.{{ $example.PrimaryResourceId }}", []string{ {{- range $key := $.ListResultDisplayNameKeyStrings }} @@ -106,8 +106,8 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { querycheck.ExpectLengthAtLeast("{{ $example.ResourceType $.TerraformName }}.list_query", 1), querycheck.ExpectResourceDisplayName( "{{ $example.ResourceType $.TerraformName }}.list_query", - queryfilter.ByDisplayName(capturedDisplayName.ExpectKnownValue()), - capturedDisplayName.ExpectKnownValue(), + queryfilter.ByDisplayName(listDisplayName.CheckValue()), + listDisplayName.CheckValue(), ), }, }, From a44b4d180766eea439f47e378fd06a909fd3cc62 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 30 Apr 2026 11:35:11 -0700 Subject: [PATCH 082/100] remove project_service --- .../fwprovider/framework_provider_mmv1_resources.go.tmpl | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl index bce0bceb985c..ba2eb00d313f 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl @@ -23,5 +23,4 @@ var generatedListResources = []func() list.ListResource{ var handwrittenListResources = []func() list.ListResource{ listResourceFunc(resourcemanager.NewGoogleServiceAccountListResource()), - listResourceFunc(resourcemanager.NewGoogleProjectServiceListResource()), } From 4976a1808533743bfb9805727973ab7ca78aeeed Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 30 Apr 2026 13:40:08 -0700 Subject: [PATCH 083/100] add conditional for setting optional true or false for list schemas --- mmv1/templates/terraform/list_resource.go.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 70dde5b5ccd8..b8a3de712a7a 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -50,7 +50,7 @@ func New{{ $.ResourceName -}}ListResource() list.ListResource { listR.SDKv2Resource = Resource{{ $.ResourceName -}}() listR.ListConfigFields = []tpgresource.ListConfigField{ {{- range $scope := $.ListScopeProperties }} - {Name: "{{ underscore $scope.Name }}", Kind: tpgresource.ListConfigKindString, Optional: true}, + {Name: "{{ underscore $scope.Name }}", Kind: tpgresource.ListConfigKindString, Optional: {{ if $scope.Required }}false{{ else }}true{{ end }}}, {{- end }} } return listR From c8984eff2b439d96d9ef8fc078ee55139f5b150d Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Thu, 30 Apr 2026 16:40:43 -0700 Subject: [PATCH 084/100] add itemName fallback for default collection_key_url useage --- mmv1/products/cloudrun/Service.yaml | 1 - .../terraform/samples/base_configs/query_test_file.go.tmpl | 5 ----- 2 files changed, 6 deletions(-) diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 2c81fc9e4283..4edfa4adde72 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -34,7 +34,6 @@ datasource_experimental: generate: true exclude_test: true generate_list_resource: true -collection_url_key: 'items' timeouts: insert_minutes: 20 update_minutes: 20 diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index 2f3e56ecc36b..a4cac1b1591e 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -46,17 +46,12 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { {{- range $varKey, $varVal := $example.TestContextVars }} "{{$varKey}}": {{$varVal}}, {{- end }} - {{- range $varKey, $varVal := $example.TestVarsOverrides }} - "{{$varKey}}": {{$varVal}}, - {{- end }} {{- range $scope := $.ListScopeProperties }} {{- $n := underscore $scope.Name }} {{- if or (eq $n "region") (eq $n "location") }} "{{$n}}": envvar.GetTestRegionFromEnv(), {{- else if eq $n "zone" }} "zone": envvar.GetTestZoneFromEnv(), - {{- else if eq $n "project" }} - "project": acctest.BootstrapProject(t, "tf-bt-list-", envvar.GetTestBillingAccountFromEnv(t), nil).ProjectId, {{- end }} {{- end }} "random_suffix": randomSuffix, From 3bfbd152b6230e4b4bcc747b5ad7725816bceb97 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 14:42:15 -0700 Subject: [PATCH 085/100] include registry init for list resources in list_resource.go.tmpl --- .../templates/terraform/list_resource.go.tmpl | 8 ++++++ .../framework_provider_mmv1_resources.go.tmpl | 26 ------------------- 2 files changed, 8 insertions(+), 26 deletions(-) delete mode 100644 mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index b8a3de712a7a..88f6df48907a 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -38,6 +38,14 @@ import ( transport_tpg "{{ $.ImportPath }}/transport" ) +func init() { + registry.FrameworkListResource{ + Name: "{{ $.TerraformName }}", + ProductName: "{{ $.ProductMetadata.Name }}", + Func: New{{ $.ResourceName -}}ListResource, + }.Register() +} + var _ list.ListResource = &{{ $.ResourceName -}}ListResource{} type {{ $.ResourceName -}}ListResource struct { diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl deleted file mode 100644 index ba2eb00d313f..000000000000 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go.tmpl +++ /dev/null @@ -1,26 +0,0 @@ -package fwprovider - -import ( - "github.com/hashicorp/terraform-plugin-framework/list" - - "github.com/hashicorp/terraform-provider-google/google/services/resourcemanager" -{{- $listPkgs := $.GetListResourceImportPackages $.Products }} -{{- range $pkg := $listPkgs }} - "github.com/hashicorp/terraform-provider-google/google/services/{{ $pkg }}" -{{- end }} -) - -func listResourceFunc(lr list.ListResource) func() list.ListResource { - return func() list.ListResource { return lr } -} - -// generatedListResources registers MMv1-generated list resources (generate_list_resource in YAML). -var generatedListResources = []func() list.ListResource{ -{{- range $lr := $.GetGeneratedListResourcesInVersion $.Products }} - listResourceFunc({{ $lr.Package }}.{{ $lr.NewFunc }}()), -{{- end }} -} - -var handwrittenListResources = []func() list.ListResource{ - listResourceFunc(resourcemanager.NewGoogleServiceAccountListResource()), -} From 82a69cb2d0d4c192b29621610ab2180737732367 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 15:00:58 -0700 Subject: [PATCH 086/100] remove registration of list_resources in favor of registry init --- mmv1/provider/terraform.go | 44 ------------------- .../templates/terraform/list_resource.go.tmpl | 1 + 2 files changed, 1 insertion(+), 44 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index f47916f3827b..a6e10969a316 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -1096,47 +1096,3 @@ type ProviderWithProducts struct { Compiler string Products []*api.Product } - -// GeneratedListResourceRegistration describes one MMv1-generated list resource constructor -// for framework_provider_mmv1_resources.go.tmpl. -type GeneratedListResourceRegistration struct { - Package string // Go service package name (product ApiName), e.g. "cloudrun" - NewFunc string // e.g. "NewCloudRunServiceListResource" -} - -func (t Terraform) GetGeneratedListResourcesInVersion(products []*api.Product) []GeneratedListResourceRegistration { - var out []GeneratedListResourceRegistration - for _, productDefinition := range products { - for _, object := range productDefinition.Objects { - if object.NotInVersion(productDefinition.VersionObjOrClosest(t.TargetVersionName)) || object.IsExcluded() || !object.GenerateListResource { - continue - } - out = append(out, GeneratedListResourceRegistration{ - Package: productDefinition.ApiName, - NewFunc: fmt.Sprintf("New%sListResource", object.ResourceName()), - }) - } - } - slices.SortFunc(out, func(a, b GeneratedListResourceRegistration) int { - if c := strings.Compare(a.Package, b.Package); c != 0 { - return c - } - return strings.Compare(a.NewFunc, b.NewFunc) - }) - return out -} - -func (t Terraform) GetListResourceImportPackages(products []*api.Product) []string { - reg := t.GetGeneratedListResourcesInVersion(products) - seen := make(map[string]struct{}, len(reg)) - var pkgs []string - for _, r := range reg { - if _, ok := seen[r.Package]; ok { - continue - } - seen[r.Package] = struct{}{} - pkgs = append(pkgs, r.Package) - } - slices.Sort(pkgs) - return pkgs -} diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 88f6df48907a..09f82c3d373e 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -34,6 +34,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/registry" "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" ) From 1d1cdb91ce24d4640392966f224ae00afc3b3252 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 15:06:37 -0700 Subject: [PATCH 087/100] remove generate_list_resource for cloudbuild and trigger --- mmv1/products/cloudbuild/Trigger.yaml | 2 -- mmv1/products/storage/Folder.yaml | 1 - 2 files changed, 3 deletions(-) diff --git a/mmv1/products/cloudbuild/Trigger.yaml b/mmv1/products/cloudbuild/Trigger.yaml index 3402ac8c85d2..a4a37123c1da 100644 --- a/mmv1/products/cloudbuild/Trigger.yaml +++ b/mmv1/products/cloudbuild/Trigger.yaml @@ -14,7 +14,6 @@ --- name: 'Trigger' api_resource_type_kind: BuildTrigger -collection_url_key: 'triggers' api_variant_patterns: - 'projects/{project}/locations/{location}/triggers/{trigger}' description: | @@ -39,7 +38,6 @@ timeouts: insert_minutes: 20 update_minutes: 20 delete_minutes: 20 -generate_list_resource: true custom_code: constants: 'templates/terraform/constants/cloudbuild_trigger.tmpl' post_create: 'templates/terraform/post_create/cloudbuild_trigger_id.go.tmpl' diff --git a/mmv1/products/storage/Folder.yaml b/mmv1/products/storage/Folder.yaml index 881876ee84d4..c2cc0b9da102 100644 --- a/mmv1/products/storage/Folder.yaml +++ b/mmv1/products/storage/Folder.yaml @@ -24,7 +24,6 @@ timeouts: update_minutes: 20 delete_minutes: 20 exclude_sweeper: true -generate_list_resource: true import_format: - '{{bucket}}/folders/{{%name}}' - '{{bucket}}/{{%name}}' From 69a5b627af8ddd514dab6c640bdd4661d6863ca7 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 15:42:52 -0700 Subject: [PATCH 088/100] more cleanups in list_resource_method - remove meta interface{} set --- .../templates/terraform/list_resource_method.go.tmpl | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 13574570b26c..cb581afc9e7d 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -41,18 +41,12 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, ItemName: "{{ $.CollectionUrlKey }}", Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { headers := make(http.Header) -{{- if or $.CustomCode.PostRead $.NestedQuery $.CustomCode.Decoder }} - var meta interface{} = config - _ = meta -{{- end }} -{{- if or $.NestedQuery $.CustomCode.Decoder }} var err error -{{- end }} {{- if $.CustomCode.PostRead }} {{ customTemplate $ $.CustomCode.PostRead false -}} {{- end }} {{- if $.NestedQuery }} - res, err = flattenNested{{ $.ResourceName -}}(d, meta, res) + res, err = flattenNested{{ $.ResourceName -}}(d, config, res) if err != nil { return err } @@ -61,7 +55,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, } {{- end }} {{- if $.CustomCode.Decoder }} - res, err = resource{{ $.ResourceName -}}Decoder(d, meta, res) + res, err = resource{{ $.ResourceName -}}Decoder(d, config, res) if err != nil { return err } @@ -69,7 +63,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return fmt.Errorf("Error decoding {{ $.ResourceName }} from list response") } {{- end }} - if err := Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { + if err = Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { return err } {{- /* url_param_only identity fields (e.g. name) are not GettableProperties, so the flattener does not Set them. Copy from res → d here so SetId/ListResultDisplayName can find them. Integer ids sometimes arrive as strings and need coercion. */ -}} From 0164775e2c947929fa9174f03fc9b4c1eb6d47ae Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 15:44:12 -0700 Subject: [PATCH 089/100] move billingProject set in hasProject --- mmv1/templates/terraform/list_resource_method.go.tmpl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index cb581afc9e7d..ab7c5a329ad5 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -19,9 +19,10 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return err } - billingProject := "" {{- if $.HasProject }} - billingProject = project + billingProject := project +{{- else }} + billingProject := "" {{- end }} if bp, err := tpgresource.GetBillingProject(resourceData, config); err == nil { billingProject = bp From a84e02203794b0ee9cdb46bd2861bc1dfb934c09 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 15:46:17 -0700 Subject: [PATCH 090/100] minimize error messages --- mmv1/templates/terraform/list_resource_method.go.tmpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index ab7c5a329ad5..110b5b7d3feb 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -52,7 +52,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return err } if res == nil { - return fmt.Errorf("Error matching nested {{ $.ResourceName }} from list response") + return fmt.Errorf("error matching nested {{ $.ResourceName }} from list response") } {{- end }} {{- if $.CustomCode.Decoder }} @@ -61,7 +61,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return err } if res == nil { - return fmt.Errorf("Error decoding {{ $.ResourceName }} from list response") + return fmt.Errorf("error decoding {{ $.ResourceName }} from list response") } {{- end }} if err = Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { @@ -75,20 +75,20 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, if s, ok := v.(string); ok { i, err := strconv.Atoi(s) if err != nil { - return fmt.Errorf("Error coercing {{ underscore $id.Name }}: %s", err) + return fmt.Errorf("error coercing {{ underscore $id.Name }}: %w", err) } v = i } {{- end }} if err := d.Set("{{ underscore $id.Name }}", v); err != nil { - return fmt.Errorf("Error setting {{ underscore $id.Name }}: %s", err) + return fmt.Errorf("error setting {{ underscore $id.Name }}: %w", err) } } {{- end }} {{- end }} id, err := tpgresource.ReplaceVars{{if $.LegacyLongFormProject -}}ForId{{ end -}}(d, config, "{{ $.IdFormat -}}") if err != nil { - return fmt.Errorf("Error constructing id: %s", err) + return fmt.Errorf("error constructing id: %w", err) } d.SetId(id) return nil From 26eae63a01af140ce0b7dbabb034d7425062157b Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 16:01:11 -0700 Subject: [PATCH 091/100] more cleanups --- mmv1/templates/terraform/list_resource.go.tmpl | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index 09f82c3d373e..ff9c1f450207 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -24,9 +24,6 @@ import ( "errors" "fmt" "net/http" -{{- if and $.HasProject $.LegacyLongFormProject }} - "strings" -{{- end }} "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/list" @@ -89,19 +86,10 @@ func (listR *{{ $.ResourceName -}}ListResource) List(ctx context.Context, listRe } {{- range $scope := $.ListScopeProperties }} -{{- if eq $scope.Name "project" }} - {{ $scope.CamelizeProperty }} := listR.GetProject(data.{{ $scope.TitlelizeProperty }}) -{{- else if eq $scope.Name "region" }} - {{ $scope.CamelizeProperty }} := listR.GetRegion(data.{{ $scope.TitlelizeProperty }}) -{{- else if eq $scope.Name "zone" }} - {{ $scope.CamelizeProperty }} := listR.GetZone(data.{{ $scope.TitlelizeProperty }}) -{{- else if eq $scope.Name "location" }} - {{ $scope.CamelizeProperty }} := listR.GetLocation(data.{{ $scope.TitlelizeProperty }}) +{{- if or (eq $scope.Name "project") (eq $scope.Name "region") (eq $scope.Name "zone") (eq $scope.Name "location") }} + {{ $scope.CamelizeProperty }} := listR.Get{{ $scope.TitlelizeProperty }}(data.{{ $scope.TitlelizeProperty }}) {{- else }} - var {{ $scope.CamelizeProperty }} string - if !data.{{ $scope.TitlelizeProperty }}.IsNull() && !data.{{ $scope.TitlelizeProperty }}.IsUnknown() { - {{ $scope.CamelizeProperty }} = data.{{ $scope.TitlelizeProperty }}.ValueString() - } + {{ $scope.CamelizeProperty }} := data.{{ $scope.TitlelizeProperty }}.ValueString() {{- end }} {{- end }} From 4bc9ab9b8c1c69cdd1784655f06de13e89d238fc Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 16:06:53 -0700 Subject: [PATCH 092/100] add importPath for registry import --- mmv1/templates/terraform/list_resource.go.tmpl | 2 +- mmv1/templates/terraform/list_resource_method.go.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/templates/terraform/list_resource.go.tmpl b/mmv1/templates/terraform/list_resource.go.tmpl index ff9c1f450207..c378fd0325d3 100644 --- a/mmv1/templates/terraform/list_resource.go.tmpl +++ b/mmv1/templates/terraform/list_resource.go.tmpl @@ -31,7 +31,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "github.com/hashicorp/terraform-provider-google/google/registry" + "{{ $.ImportPath }}/registry" "{{ $.ImportPath }}/tpgresource" transport_tpg "{{ $.ImportPath }}/transport" ) diff --git a/mmv1/templates/terraform/list_resource_method.go.tmpl b/mmv1/templates/terraform/list_resource_method.go.tmpl index 110b5b7d3feb..0c916f49dc59 100644 --- a/mmv1/templates/terraform/list_resource_method.go.tmpl +++ b/mmv1/templates/terraform/list_resource_method.go.tmpl @@ -64,7 +64,7 @@ func List{{ $.ResourceName }}s(config *transport_tpg.Config, return fmt.Errorf("error decoding {{ $.ResourceName }} from list response") } {{- end }} - if err = Resource{{ $.ResourceName }}Flatten(d, nil, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { + if err = Resource{{ $.ResourceName }}Flatten(d, config, res, config, {{ if $.HasProject }}project, {{ end }}userAgent, billingProject, url, headers); err != nil { return err } {{- /* url_param_only identity fields (e.g. name) are not GettableProperties, so the flattener does not Set them. Copy from res → d here so SetId/ListResultDisplayName can find them. Integer ids sometimes arrive as strings and need coercion. */ -}} From db2d496c8dcc93d4ae52627bb4a8095429318466 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Mon, 4 May 2026 16:14:55 -0700 Subject: [PATCH 093/100] use slics.ContainsFunc in DisplayNameKeyStrings helper method --- mmv1/api/resource.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 370eb3df3583..62c68d3c16b3 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -726,11 +726,8 @@ func (r Resource) ListScopeProperties() []*Type { func (r Resource) ListResultDisplayNameKeyStrings() []string { var keys []string - for _, p := range r.RootProperties() { - if p.Name == "display_name" { - keys = append(keys, "display_name") - break - } + if slices.ContainsFunc(r.RootProperties(), func(p *Type) bool { return p.Name == "display_name" }) { + keys = append(keys, "display_name") } markers := regexp.MustCompile(`\{\{(\w+)\}\}`).FindAllStringSubmatch(r.IdFormat, -1) if len(markers) > 0 { From a300a51326c08fb03befe91f56c038a2471750e1 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 5 May 2026 11:27:30 -0700 Subject: [PATCH 094/100] use hasEligibleExample method in listResourceQueryTest generation --- mmv1/provider/terraform.go | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index a6e10969a316..810499839208 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -273,24 +273,11 @@ func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateD return } - eligibleExample := false - for _, example := range object.Examples { - if !example.ExcludeTest { - if object.ProductMetadata.VersionObjOrClosest(t.Product.Version.Name).CompareTo(object.ProductMetadata.VersionObjOrClosest(example.MinVersion)) >= 0 { - eligibleExample = true - break - } - } - } - if !eligibleExample { + if !t.hasEligibleExample(object) { return } - productName := t.Product.ApiName - targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName) - if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { - log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) - } + targetFolder := t.makeFolder(outputFolder, t.FolderName(), "services", t.Product.ApiName) targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s_generated_test.go", t.ResourceGoFilename(object))) templateData.GenerateQueryTestFile(targetFilePath, object) } From e12d36c9bfae5ed1d062ba69b1f2cf524a6f7b67 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 5 May 2026 11:28:53 -0700 Subject: [PATCH 095/100] combine example check as one --- mmv1/provider/terraform.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 810499839208..151c6fbc9b6b 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -269,11 +269,7 @@ func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateD if object.Samples != nil && object.Examples != nil { log.Fatalf("Both Samples and Examples block exist in %v", object.Name) } - if object.Examples == nil { - return - } - - if !t.hasEligibleExample(object) { + if object.Examples == nil || !t.hasEligibleExample(object) { return } From 99bd825acfa208e4f4c4d87985d9fc83ed30eaea Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 5 May 2026 11:33:56 -0700 Subject: [PATCH 096/100] match main --- .../resourcemanager/list_google_service_account_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go b/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go index 80e33254ad1f..dad55c8fda05 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go @@ -23,7 +23,7 @@ func TestAccServiceAccountListResource_queryIdentity(t *testing.T) { accountId := "a" + acctest.RandString(t, 10) project := envvar.GetTestProjectFromEnv() expectedEmail := fmt.Sprintf("%s@%s.iam.gserviceaccount.com", accountId, project) - var listDisplayName = acctest.ListDisplayName{} + listDisplayName := acctest.ListDisplayName{} acctest.VcrTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ @@ -37,7 +37,7 @@ func TestAccServiceAccountListResource_queryIdentity(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("google_service_account.acceptance", "email", expectedEmail), resource.TestCheckResourceAttr("google_service_account.acceptance", "project", project), - listDisplayName.Capture("google_service_account.acceptance", []string{"display_name"}), + listDisplayName.Capture("google_service_account.acceptance", []string{"display_name", "email"}), ), }, { From 82a7deb5692f0553b62635488518088acefdd6e9 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 5 May 2026 11:51:59 -0700 Subject: [PATCH 097/100] move list generation to within generateResource --- mmv1/provider/terraform.go | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 151c6fbc9b6b..5635bbfa69ba 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -113,9 +113,6 @@ func (t *Terraform) GenerateObject(object api.Resource, outputFolder, productPat t.GenerateSingularDataSourceTests(object, *templateData, outputFolder) // log.Printf("Generating %s metadata", object.Name) t.GenerateResourceMetadata(object, *templateData, outputFolder) - if object.GenerateListResource { - t.GenerateListResourceQueryTest(object, *templateData, outputFolder) - } } } @@ -158,19 +155,8 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s.go", t.ResourceGoFilename(object))) templateData.GenerateResourceFile(targetFilePath, object) } - if object.GenerateListResource { - if object.ExcludeIdentityGeneration { - log.Fatalf("generate_list_resource requires identity support; remove exclude_identity_generation from resource %q or disable generate_list_resource", object.Name) - } - if object.ExcludeRead { - log.Fatalf("generate_list_resource requires read support; remove exclude_read from resource %q or disable generate_list_resource", object.Name) - } - targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s.go", t.ResourceGoFilename(object))) - templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, - "templates/terraform/list_resource.go.tmpl", - "templates/terraform/list_resource_method.go.tmpl", - ) - } + + t.GenerateListResource(object, templateData, targetFolder) } if generateDocs { @@ -180,6 +166,24 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD } } +func (t *Terraform) GenerateListResource(object api.Resource, templateData TemplateData, targetFolder string) { + if object.GenerateListResource { + if object.ExcludeIdentityGeneration { + log.Fatalf("generate_list_resource requires identity support; remove exclude_identity_generation from resource %q or disable generate_list_resource", object.Name) + } + if object.ExcludeRead { + log.Fatalf("generate_list_resource requires read support; remove exclude_read from resource %q or disable generate_list_resource", object.Name) + } + targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s.go", t.ResourceGoFilename(object))) + templateData.GenerateFile(targetFilePath, "templates/terraform/list_resource.go.tmpl", object, true, + "templates/terraform/list_resource.go.tmpl", + "templates/terraform/list_resource_method.go.tmpl", + ) + + t.GenerateListResourceQueryTest(object, templateData, targetFolder) + } +} + // GenerateResourceFile is the Bazel counterpart to GenerateResource(), generating *only() the .go file and // taking the full path to the output file to generate rather than implicitly generating the path. func (t *Terraform) GenerateResourceFile(object api.Resource, targetFilePath string) { @@ -265,15 +269,13 @@ func (t *Terraform) GenerateResourceTests(object api.Resource, templateData Temp templateData.GenerateTestFile(targetFilePath, object) } -func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateData TemplateData, outputFolder string) { +func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateData TemplateData, targetFolder string) { if object.Samples != nil && object.Examples != nil { log.Fatalf("Both Samples and Examples block exist in %v", object.Name) } if object.Examples == nil || !t.hasEligibleExample(object) { return } - - targetFolder := t.makeFolder(outputFolder, t.FolderName(), "services", t.Product.ApiName) targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s_generated_test.go", t.ResourceGoFilename(object))) templateData.GenerateQueryTestFile(targetFilePath, object) } From 7f54ccc6a6a87386bf77a1788a4182304bef7f32 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 5 May 2026 11:52:54 -0700 Subject: [PATCH 098/100] remove emptyline --- .../services/resourcemanager/list_google_service_account_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go b/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go index dad55c8fda05..f9dca1d8cf7c 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/list_google_service_account_test.go @@ -24,7 +24,6 @@ func TestAccServiceAccountListResource_queryIdentity(t *testing.T) { project := envvar.GetTestProjectFromEnv() expectedEmail := fmt.Sprintf("%s@%s.iam.gserviceaccount.com", accountId, project) listDisplayName := acctest.ListDisplayName{} - acctest.VcrTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBelow(tfversion.Version1_14_0), From 59a3fc686f8bbce940f194931631d79e39414c96 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Tue, 5 May 2026 14:32:51 -0700 Subject: [PATCH 099/100] documentation generation for list-resources --- mmv1/provider/template_data.go | 8 +++ mmv1/provider/terraform.go | 6 +++ .../list_resource.html.markdown.tmpl | 54 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 mmv1/templates/terraform/list_resource.html.markdown.tmpl diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index cfd5df7d840a..c54c0290d8f6 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -122,6 +122,14 @@ func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api. td.GenerateFile(filePath, templatePath, resource, false, templates...) } +func (td *TemplateData) GenerateListResourceDocumentationFile(filePath string, resource api.Resource) { + templatePath := "templates/terraform/list_resource.html.markdown.tmpl" + templates := []string{ + templatePath, + } + td.GenerateFile(filePath, templatePath, resource, false, templates...) +} + func (td *TemplateData) GenerateTestFileLegacy(filePath string, resource api.Resource) { templatePath := "templates/terraform/examples/base_configs/test_file.go.tmpl" templates := []string{ diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 5635bbfa69ba..4fcf46e06f8b 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -163,6 +163,12 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD targetFolder := t.makeFolder(outputFolder, "website", "docs", "r") targetFilePath := path.Join(targetFolder, fmt.Sprintf("%s.html.markdown", t.FullResourceName(object))) templateData.GenerateDocumentationFile(targetFilePath, object) + + if object.GenerateListResource { + listDocFolder := t.makeFolder(outputFolder, "website", "docs", "list-resources") + listDocFilePath := path.Join(listDocFolder, fmt.Sprintf("%s.html.markdown", object.TerraformName())) + templateData.GenerateListResourceDocumentationFile(listDocFilePath, object) + } } } diff --git a/mmv1/templates/terraform/list_resource.html.markdown.tmpl b/mmv1/templates/terraform/list_resource.html.markdown.tmpl new file mode 100644 index 000000000000..e99ce4564186 --- /dev/null +++ b/mmv1/templates/terraform/list_resource.html.markdown.tmpl @@ -0,0 +1,54 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +--- +{{$.MarkdownHeader TemplatePath}} +subcategory: "{{$.ProductMetadata.DisplayName}}" +description: |- + List {{$.ProductMetadata.DisplayName}} {{lower $.Name}} resources in a project for use with terraform query + and .tfquery.hcl files. +--- + +# {{$.TerraformName}} (list) + +Lists [`{{$.TerraformName}}`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/{{$.TerraformName}}) resources for use with [`terraform query`](https://developer.hashicorp.com/terraform/cli/commands/query) and **`.tfquery.hcl`** files. + +For how list resources work in this provider, file layout, Terraform version requirements, and shared `list` block arguments, refer to the guide [Use list resources with terraform query (Google Cloud provider)](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/using_list_resources_with_terraform_query). + +## Example + +```hcl +list "{{$.TerraformName}}" "all" { + provider = {{ if eq $.MinVersion "beta" }}google-beta{{ else }}google{{ end }} + + config { +{{- range $scope := $.ListScopeProperties }} + {{ underscore $scope.Name }} = {{ if $scope.Required }}"..."{{ else }}"..." # Optional{{ end }} +{{- end }} + } +} +``` + +Run `terraform query` from the directory that contains the `.tfquery.hcl` file. + +## Configuration (`config` block) + +{{- range $scope := $.ListScopeProperties }} +* `{{ underscore $scope.Name }}` - ({{ if $scope.Required }}Required{{ else }}Optional{{ end }}){{ if $scope.Description }} {{ $scope.Description }}{{ end }} +{{- end }} + +## Results + +By default each result includes **resource identity** for [`{{$.TerraformName}}`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/{{$.TerraformName}}) (see [Resource identity](https://developer.hashicorp.com/terraform/language/resources/identities)). + +With `include_resource = true` on the `list` block, results also include the full resource-style attributes documented for the managed [`{{$.TerraformName}}` resource](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/{{$.TerraformName}}#attributes-reference). From 7435c8461a1f1f9ee51034fd2a23ebd3f0ccd519 Mon Sep 17 00:00:00 2001 From: "alvarez.mauriciotm@gmail.com" Date: Wed, 6 May 2026 13:20:24 -0700 Subject: [PATCH 100/100] MIGRATION: query_test.go.tmpl uses samples --- mmv1/provider/terraform.go | 2 +- .../base_configs/query_test_file.go.tmpl | 37 +++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 4fcf46e06f8b..5a4c1e25b8b7 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -279,7 +279,7 @@ func (t *Terraform) GenerateListResourceQueryTest(object api.Resource, templateD if object.Samples != nil && object.Examples != nil { log.Fatalf("Both Samples and Examples block exist in %v", object.Name) } - if object.Examples == nil || !t.hasEligibleExample(object) { + if object.Samples == nil || !t.hasEligibleSample(object) { return } targetFilePath := path.Join(targetFolder, fmt.Sprintf("list_%s_generated_test.go", t.ResourceGoFilename(object))) diff --git a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl index a4cac1b1591e..1610ee5fbb80 100644 --- a/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +++ b/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl @@ -21,17 +21,18 @@ var ( _ = envvar.TestEnvVar ) -{{ $example := $.FirstTestExample }} +{{ $sample := $.FirstTestConfig.Sample }} +{{ $step := $.FirstTestConfig.Step }} func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { t.Parallel() - {{- if $example.SkipVcr }} + {{- if $sample.SkipVcr }} acctest.SkipIfVcr(t) {{- end }} - {{- if $example.BootstrapIam }} + {{- if $sample.BootstrapIam }} acctest.BootstrapIamMembers(t, []acctest.IamMember{ - {{- range $iam := $example.BootstrapIam }} + {{- range $iam := $sample.BootstrapIam }} { Member: "{{$iam.Member}}", Role: "{{$iam.Role}}", @@ -42,8 +43,8 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { randomSuffix := acctest.RandString(t, 10) context := map[string]interface{}{ - {{- template "EnvVarContext" dict "TestEnvVars" $example.TestEnvVars "HasNewLine" false}} - {{- range $varKey, $varVal := $example.TestContextVars }} + {{- template "EnvVarContext" dict "TestEnvVars" $step.TestEnvVars "HasNewLine" false}} + {{- range $varKey, $varVal := $step.TestContextVars }} "{{$varKey}}": {{$varVal}}, {{- end }} {{- range $scope := $.ListScopeProperties }} @@ -57,21 +58,19 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { "random_suffix": randomSuffix, } - // Captured at create-step time and asserted against list-query results. var listDisplayName acctest.ListDisplayName - acctest.VcrTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBelow(tfversion.Version1_14_0), }, PreCheck: func() { acctest.AccTestPreCheck(t) }, -{{- if $.VersionedProvider $example.MinVersion }} +{{- if $.VersionedProvider $sample.MinVersion }} ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), {{- else }} ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - {{- if $example.ExternalProviders }} + {{- if $sample.ExternalProviders }} ExternalProviders: map[string]resource.ExternalProvider{ - {{- range $provider := $example.ExternalProviders }} + {{- range $provider := $sample.ExternalProviders }} "{{$provider}}": {}, {{- end }} }, @@ -82,10 +81,10 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { {{- end }} Steps: []resource.TestStep{ { - Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}(context), + Config: testAcc{{ $step.TestStepSlug $.ProductMetadata.Name $.Name }}(context), Check: resource.ComposeTestCheckFunc( listDisplayName.Capture( - "{{ $example.ResourceType $.TerraformName }}.{{ $example.PrimaryResourceId }}", + "{{ $sample.ResourceType $.TerraformName }}.{{ $sample.PrimaryResourceId }}", []string{ {{- range $key := $.ListResultDisplayNameKeyStrings }} "{{ $key }}", @@ -96,11 +95,11 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { }, { Query: true, - Config: testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context), + Config: testAcc{{ $step.TestStepSlug $.ProductMetadata.Name $.Name }}ListQuery(context), QueryResultChecks: []querycheck.QueryResultCheck{ - querycheck.ExpectLengthAtLeast("{{ $example.ResourceType $.TerraformName }}.list_query", 1), + querycheck.ExpectLengthAtLeast("{{ $sample.ResourceType $.TerraformName }}.list_query", 1), querycheck.ExpectResourceDisplayName( - "{{ $example.ResourceType $.TerraformName }}.list_query", + "{{ $sample.ResourceType $.TerraformName }}.list_query", queryfilter.ByDisplayName(listDisplayName.CheckValue()), listDisplayName.CheckValue(), ), @@ -110,10 +109,10 @@ func TestAcc{{ $.ResourceName }}ListQuery_generated(t *testing.T) { }) } -func testAcc{{ $example.TestSlug $.ProductMetadata.Name $.Name }}ListQuery(context map[string]interface{}) string { +func testAcc{{ $step.TestStepSlug $.ProductMetadata.Name $.Name }}ListQuery(context map[string]interface{}) string { return acctest.Nprintf(` -list "{{ $example.ResourceType $.TerraformName }}" "list_query" { - provider = {{ if $.VersionedProvider $example.MinVersion }}google-beta{{ else }}google{{ end }} +list "{{ $sample.ResourceType $.TerraformName }}" "list_query" { + provider = {{ if $.VersionedProvider $sample.MinVersion }}google-beta{{ else }}google{{ end }} config { {{- range $scope := $.ListScopeProperties }} {{ underscore $scope.Name }} = "%{{"{"}}{{ underscore $scope.Name }}{{"}"}}"