diff --git a/mmv1/products/bigqueryanalyticshub/Listing.yaml b/mmv1/products/bigqueryanalyticshub/Listing.yaml index 998a07f6f0c6..b3aa8ea2f48a 100644 --- a/mmv1/products/bigqueryanalyticshub/Listing.yaml +++ b/mmv1/products/bigqueryanalyticshub/Listing.yaml @@ -43,78 +43,120 @@ custom_code: pre_delete: 'templates/terraform/pre_delete/bigquery_analytics_hub_listing.go.tmpl' # Skipping the sweeper due to the non-standard base_url exclude_sweeper: true -examples: +samples: - name: 'bigquery_analyticshub_listing_basic' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'my_data_exchange' - listing_id: 'my_listing' - desc: 'example data exchange' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_basic.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'my_data_exchange' + listing_id: 'my_listing' + desc: 'example data exchange' - name: 'bigquery_analyticshub_listing_restricted' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'my_data_exchange' - listing_id: 'my_listing' - desc: 'example data exchange' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_restricted.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'my_data_exchange' + listing_id: 'my_listing' + desc: 'example data exchange' - name: 'bigquery_analyticshub_listing_dcr' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'dcr_data_exchange' - listing_id: 'dcr_listing' - desc: 'example dcr data exchange' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_dcr.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'dcr_data_exchange' + listing_id: 'dcr_listing' + desc: 'example dcr data exchange' - name: 'bigquery_analyticshub_listing_log_linked_dataset_query_user' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_log_email_de%s", context["random_suffix"]),fmt.Sprintf("tf_test_log_email_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'tf_test_log_email_de' - listing_id: 'tf_test_log_email_listing' - dataset_id: 'tf_test_log_email_ds' - description: 'Example for log email test' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_log_linked_dataset_query_user.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'tf_test_log_email_de' + listing_id: 'tf_test_log_email_listing' + dataset_id: 'tf_test_log_email_ds' + description: 'Example for log email test' - name: 'bigquery_analyticshub_listing_pubsub' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_pubsub_de%s", context["random_suffix"]),fmt.Sprintf("tf_test_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'tf_test_pubsub_data_exchange' - listing_id: 'tf_test_pubsub_listing' - pubsub_topic_name: 'test_pubsub' - description: 'Example for pubsub topic source' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_pubsub.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'tf_test_pubsub_data_exchange' + listing_id: 'tf_test_pubsub_listing' + pubsub_topic_name: 'test_pubsub' + description: 'Example for pubsub topic source' - name: 'bigquery_analyticshub_listing_dcr_routine' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_pubsub_de%s", context["random_suffix"]),fmt.Sprintf("tf_test_listing%s", context["random_suffix"])' region_override: 'US' min_version: beta - vars: - data_exchange_id: 'tf_test_data_exchange' - listing_id: 'tf_test_listing_routine' - dataset_id: 'tf_test_dataset' - routine_id: 'tf_test_routine' - desc: 'Example for listing with routine' - - name: 'bigquery_analyticshub_public_listing' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_dcr_routine.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'tf_test_data_exchange' + listing_id: 'tf_test_listing_routine' + dataset_id: 'tf_test_dataset' + routine_id: 'tf_test_routine' + desc: 'Example for listing with routine' + - name: 'bigquery_analyticshub_listing_multiregion' primary_resource_id: 'listing' + min_version: beta primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'my_data_exchange' - listing_id: 'my_listing' - desc: 'example public listing' + steps: + - name: 'multiregion' + config_path: 'templates/terraform/samples/services/bigqueryanalyticshub/multiregion.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'my_data_exchange' + listing_id: 'my_listing' + description: 'example listing for multiregion' + exclude_test: true - name: 'bigquery_analyticshub_listing_marketplace' primary_resource_id: 'listing' primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' region_override: 'us' - vars: - data_exchange_id: 'my_data_exchange' - listing_id: 'my_listing' - desc: 'example data exchange' - ignore_read_extra: - - 'delete_commercial' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_marketplace.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'my_data_exchange' + listing_id: 'my_listing' + desc: 'example data exchange' + ignore_read_extra: + - 'delete_commercial' virtual_fields: - name: 'delete_commercial' type: Boolean @@ -148,6 +190,7 @@ properties: url_param_only: true required: true immutable: true + diff_suppress_func: 'tpgresource.CaseDiffSuppress' - name: 'displayName' type: String description: |- @@ -206,7 +249,6 @@ properties: - name: 'bigqueryDataset' type: NestedObject description: Shared dataset i.e. BigQuery dataset source. - immutable: true exactly_one_of: - 'pubsubTopic' - 'bigqueryDataset' @@ -245,6 +287,43 @@ properties: exactly_one_of: - 'table' - 'routine' + - name: 'replicaLocations' + type: Array + is_set: true + min_version: 'beta' + set_hash_func: 'tpgresource.CaseInsensitiveHash' + description: | + A list of regions where the publisher has created shared dataset replicas. + item_type: + type: String + diff_suppress_func: 'tpgresource.CaseDiffSuppress' + - name: 'effectiveReplicas' + type: Array + description: | + Server owned effective state of replicas. Contains both primary and secondary replicas. + Each replica includes a system-computed (output-only) state and primary designation. + output: true + min_version: 'beta' + item_type: + type: NestedObject + properties: + - name: 'location' + type: String + description: | + The geographic location where the replica resides. + output: true + - name: 'replicaState' + type: String + description: | + Output-only. Assigned by Analytics Hub based on real BigQuery replication state. + Possible values: REPLICA_STATE_UNSPECIFIED, READY_TO_USE, UNAVAILABLE + output: true + - name: 'primaryState' + type: String + description: | + Output-only. Indicates that this replica is the primary replica. + Possible values: PRIMARY_STATE_UNSPECIFIED, PRIMARY_REPLICA + output: true - name: 'pubsubTopic' type: NestedObject description: Pub/Sub topic source. @@ -286,7 +365,7 @@ properties: If true, restrict export of query result derived from restricted linked dataset table. - name: 'logLinkedDatasetQueryUserEmail' type: Boolean - description: + description: | If true, subscriber email logging is enabled and all queries on the linked dataset will log the email address of the querying user. Once enabled, this setting cannot be turned off. - name: 'state' type: String diff --git a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml index fcf4c321a671..aaeb695f0759 100644 --- a/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml +++ b/mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml @@ -38,20 +38,37 @@ custom_code: sweeper: url_substitutions: - region: "US" -examples: +samples: - name: 'bigquery_analyticshub_listing_subscription_basic' primary_resource_id: 'subscription' - primary_resource_name: 'fmt.Sprintf(\"tf_test_my_data_exchange%s\", - context[\"\ - random_suffix\"]), fmt.Sprintf(\"tf_test_my_listing%s\", - context[\"random_suffix\"\ - ])' + primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' region_override: 'US' - vars: - data_exchange_id: 'my_data_exchange' - listing_id: 'my_listing' - destination_dataset_id: 'destination_dataset' - description: 'example data exchange' + steps: + - name: 'basic' + config_path: 'templates/terraform/examples/bigquery_analyticshub_listing_subscription_basic.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'my_data_exchange' + listing_id: 'my_listing' + destination_dataset_id: 'destination_dataset' + description: 'example data exchange' + - name: 'bigquery_analyticshub_listing_subscription_multiregion' + primary_resource_id: 'subscription' + min_version: beta + primary_resource_name: 'fmt.Sprintf("tf_test_my_data_exchange%s", context["random_suffix"]), fmt.Sprintf("tf_test_my_listing%s", context["random_suffix"])' + region_override: 'US' + steps: + - name: 'subscription_multiregion' + config_path: 'templates/terraform/samples/services/bigqueryanalyticshub/subscription_multiregion.tf.tmpl' + test_env_vars: + project_name: 'PROJECT_NAME' + vars: + data_exchange_id: 'my_data_exchange' + listing_id: 'my_listing' + destination_dataset_id: 'destination_dataset' + description: 'example listing multiregion subscription' + exclude_test: true parameters: - name: 'dataExchangeId' type: String @@ -112,6 +129,16 @@ properties: description: | The labels associated with this dataset. You can use these to organize and group your datasets. + - name: 'replicaLocations' + is_set: true + type: Array + min_version: 'beta' + set_hash_func: 'tpgresource.CaseInsensitiveHash' + description: | + List of regions where the subscriber wants dataset replicas. + item_type: + type: String + diff_suppress_func: 'tpgresource.CaseDiffSuppress' - name: 'name' type: String description: |- diff --git a/mmv1/templates/terraform/pre_update/bigqueryanalyticshub_listing.go.tmpl b/mmv1/templates/terraform/pre_update/bigqueryanalyticshub_listing.go.tmpl index de4b967c57d4..d1327861c1b2 100644 --- a/mmv1/templates/terraform/pre_update/bigqueryanalyticshub_listing.go.tmpl +++ b/mmv1/templates/terraform/pre_update/bigqueryanalyticshub_listing.go.tmpl @@ -2,19 +2,26 @@ if d.HasChange("pubsub_topic.0.data_affinity_regions"){ // Split URL into base and query parts parts := strings.SplitN(url, "?", 2) if len(parts) == 2 { - base := parts[0] - query := parts[1] + base := parts[0] + query := parts[1] - query = strings.ReplaceAll(query, "%2C", ",") - query = strings.ReplaceAll(query, "%2c", ",") + // Replace "pubsubTopic" with "pubsubTopic.dataAffinityRegions" + query = strings.ReplaceAll(query, "pubsubTopic", "pubsubTopic.dataAffinityRegions") - // Replace "pubsubTopic" with "pubsubTopic.dataAffinityRegions" - query = strings.ReplaceAll(query, "pubsubTopic", "pubsubTopic.dataAffinityRegions") + url = base + "?" + query + } +} - // Re-encode commas back - query = strings.ReplaceAll(query, ",", "%2C") +if d.HasChange("bigquery_dataset.0.replica_locations"){ + // Split URL into base and query parts + parts := strings.SplitN(url, "?", 2) + if len(parts) == 2 { + base := parts[0] + query := parts[1] + + // Replace "bigqueryDataset" with "bigqueryDataset.replicaLocations" + query = strings.ReplaceAll(query, "bigqueryDataset", "bigqueryDataset.replicaLocations") - url = base + "?" + query + url = base + "?" + query } } - diff --git a/mmv1/templates/terraform/samples/services/bigqueryanalyticshub/multiregion.tf.tmpl b/mmv1/templates/terraform/samples/services/bigqueryanalyticshub/multiregion.tf.tmpl new file mode 100644 index 000000000000..524f066938b8 --- /dev/null +++ b/mmv1/templates/terraform/samples/services/bigqueryanalyticshub/multiregion.tf.tmpl @@ -0,0 +1,19 @@ +resource "google_bigquery_analytics_hub_data_exchange" "{{$.PrimaryResourceId}}" { + location = "us" + data_exchange_id = "{{index $.Vars "data_exchange_id"}}" + display_name = "{{index $.Vars "data_exchange_id"}}" + description = "{{index $.Vars "description"}}" +} + +resource "google_bigquery_analytics_hub_listing" "{{$.PrimaryResourceId}}" { + location = "us" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.{{$.PrimaryResourceId}}.data_exchange_id + listing_id = "{{index $.Vars "listing_id"}}" + display_name = "{{index $.Vars "listing_id"}}" + description = "{{index $.Vars "description"}}" + + bigquery_dataset { + dataset = "projects/project_id/datasets/my_listing_example2" + replica_locations = ["eu"] + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/samples/services/bigqueryanalyticshub/subscription_multiregion.tf.tmpl b/mmv1/templates/terraform/samples/services/bigqueryanalyticshub/subscription_multiregion.tf.tmpl new file mode 100644 index 000000000000..03e28b5211f4 --- /dev/null +++ b/mmv1/templates/terraform/samples/services/bigqueryanalyticshub/subscription_multiregion.tf.tmpl @@ -0,0 +1,39 @@ +resource "google_bigquery_analytics_hub_data_exchange" "{{$.PrimaryResourceId}}" { + location = "us" + data_exchange_id = "{{index $.Vars "data_exchange_id"}}" + display_name = "{{index $.Vars "data_exchange_id"}}" + description = "{{index $.Vars "description"}}" +} + +resource "google_bigquery_analytics_hub_listing" "{{$.PrimaryResourceId}}" { + location = "us" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.{{$.PrimaryResourceId}}.data_exchange_id + listing_id = "{{index $.Vars "listing_id"}}" + display_name = "{{index $.Vars "listing_id"}}" + description = "{{index $.Vars "description"}}" + + bigquery_dataset { + dataset = "projects/project_id/datasets/my_listing_example2" + replica_locations = ["eu"] + } +} + +resource "google_bigquery_analytics_hub_listing_subscription" "{{$.PrimaryResourceId}}" { + location = "US" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.{{$.PrimaryResourceId}}.data_exchange_id + listing_id = google_bigquery_analytics_hub_listing.{{$.PrimaryResourceId}}.listing_id + + destination_dataset { + description = "{{index $.Vars "description"}}" + friendly_name = "My Destination Dataset" + labels = { + testing = "123" + } + location = "US" + dataset_reference { + dataset_id = "{{index $.Vars "destination_dataset_id"}}" + project_id = google_bigquery_analytics_hub_data_exchange.{{$.PrimaryResourceId}}.project + } + replica_locations = ["eu"] + } +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go.tmpl b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go.tmpl index 2c158386e146..7a720dff4f6c 100644 --- a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go.tmpl +++ b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go.tmpl @@ -35,6 +35,7 @@ import ( "google.golang.org/api/serviceusage/v1" sqladmin "google.golang.org/api/sqladmin/v1beta4" backupdr "google.golang.org/api/backupdr/v1" + "cloud.google.com/go/bigquery" ) var SharedKeyRing = "tftest-shared-keyring-1" @@ -2399,3 +2400,100 @@ func BootstrapIntegrationsClient(t *testing.T, locationID string) BootstrapClien IsGMEK: true, } } + +func AddBigQueryDatasetReplica(projectID string,datasetID string,primaryLocation string,replicaLocation string) (string, error){ + ctx := context.Background() + + client, err := bigquery.NewClient(ctx, projectID) + if err != nil { + return "", fmt.Errorf("failed to create BigQuery client: %w", err) + } + defer client.Close() + + log.Printf("INFO: Attempting to create dataset '%s' in project '%s' at location '%s'", datasetID, projectID, primaryLocation) + datasetRef := client.Dataset(datasetID) + datasetMetadata := &bigquery.DatasetMetadata{ + Location: primaryLocation, + } + + err = datasetRef.Create(ctx, datasetMetadata) + if err != nil { + log.Printf("failed to create BigQuery dataset '%s'.Dataset already exists.", datasetID) + } else { + log.Printf("INFO: Successfully created BigQuery dataset '%s' at location '%s'.", datasetID, primaryLocation) + } + + sqlQuery := fmt.Sprintf( + "ALTER SCHEMA `%s` ADD REPLICA `%s` OPTIONS(location=`%s`)", + datasetID, + replicaLocation, + replicaLocation, + ) + + log.Printf("INFO: Executing BigQuery DDL query: %s", sqlQuery) + + query := client.Query(sqlQuery) + + job, err := query.Run(ctx) + if err != nil { + return "", fmt.Errorf("failed to submit BigQuery DDL job: %w", err) + } + + status, err := job.Wait(ctx) + if err != nil { + log.Printf("failed to wait for BigQuery job completion: %v", err) + } + + if status.Err() != nil { + log.Printf("BigQuery job completed with an error: %v", status.Err()) + } + + log.Println("Successfully added BigQuery dataset replica using the Go client library.") + + fullDatasetLocation := fmt.Sprintf("projects/%s/datasets/%s", projectID, datasetID) + return fullDatasetLocation, nil +} + +func CleanupBigQueryDatasetAndReplica(projectID, datasetID, replicaLocation string) { + log.Printf("[DEBUG] Cleanup: Starting cleanup for BigQuery dataset: projects/%s/datasets/%s", projectID, datasetID) + cleanupCtx := context.Background() + + client, cerr := bigquery.NewClient(cleanupCtx, projectID) + if cerr != nil { + log.Printf("[ERROR] Cleanup: Failed to create BigQuery client for dataset %s: %v", datasetID, cerr) + return + } + defer client.Close() + + // Attempt to remove the replica first + dropReplicaSQL := fmt.Sprintf( + "ALTER SCHEMA `%s` DROP REPLICA `%s`", + datasetID, + replicaLocation, + ) + log.Printf("[DEBUG] Cleanup: Dropping replica with SQL: %s", dropReplicaSQL) + dropQuery := client.Query(dropReplicaSQL) + dropJob, dropErr := dropQuery.Run(cleanupCtx) + if dropErr != nil { + log.Printf("[ERROR] Cleanup: Failed to submit BigQuery DDL job for dropping replica %s of dataset %s: %v", replicaLocation, datasetID, dropErr) + } else { + dropStatus, dropWaitErr := dropJob.Wait(cleanupCtx) + if dropWaitErr != nil { + log.Printf("[ERROR] Cleanup: Failed to wait for BigQuery job completion for dropping replica %s of dataset %s: %v", replicaLocation, datasetID, dropWaitErr) + } else if dropStatus.Err() != nil { + log.Printf("[ERROR] Cleanup: BigQuery job for dropping replica %s of dataset %s completed with an error: %v", replicaLocation, datasetID, dropStatus.Err()) + } else { + log.Printf("[INFO] Cleanup: Successfully dropped BigQuery dataset replica: %s for dataset %s", replicaLocation, datasetID) + } + } + + //Delete the main dataset (including any remaining contents) + log.Printf("[DEBUG] Cleanup: Deleting main BigQuery dataset: %s", datasetID) + err := client.Dataset(datasetID).DeleteWithContents(cleanupCtx) + if err != nil { + // Cannot differentiate. + log.Printf("[ERROR] Cleanup: Failed to delete BigQuery dataset %s: %v", datasetID, err) + } else { + log.Printf("[INFO] Cleanup: Successfully deleted BigQuery dataset: %s", datasetID) + } +} diff --git a/mmv1/third_party/terraform/go.mod b/mmv1/third_party/terraform/go.mod index ca30de082db8..675987d6a158 100644 --- a/mmv1/third_party/terraform/go.mod +++ b/mmv1/third_party/terraform/go.mod @@ -45,13 +45,15 @@ require ( require ( bitbucket.org/creachadair/stringset v0.0.8 // indirect cel.dev/expr v0.24.0 // indirect - cloud.google.com/go v0.121.0 // indirect + cloud.google.com/go v0.121.6 // indirect + cloud.google.com/go/bigquery v1.72.0 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/longrunning v0.6.7 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/agext/levenshtein v1.2.2 // indirect + github.com/apache/arrow/go/v15 v15.0.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -65,8 +67,10 @@ require ( github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/golang/glog v1.2.5 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/flatbuffers v23.5.26+incompatible // indirect github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect @@ -84,6 +88,8 @@ require ( github.com/hashicorp/terraform-registry-address v0.4.0 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.2 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -93,6 +99,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.1.0 // indirect + github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect @@ -100,6 +107,7 @@ require ( github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zclconf/go-cty v1.17.0 // indirect + github.com/zeebo/xxh3 v1.0.2 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect @@ -112,9 +120,11 @@ require ( golang.org/x/mod v0.29.0 // indirect golang.org/x/sync v0.18.0 // indirect golang.org/x/sys v0.38.0 // indirect + golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.38.0 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 87492669cb4a..f6336a5f8158 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -5,10 +5,14 @@ cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.121.0 h1:pgfwva8nGw7vivjZiRfrmglGWiCJBP+0OmDpenG/Fwg= cloud.google.com/go v0.121.0/go.mod h1:rS7Kytwheu/y9buoDmu5EIpMMCI4Mb8ND4aeN4Vwj7Q= +cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c= +cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI= cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4= cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/bigquery v1.72.0 h1:D/yLju+3Ens2IXx7ou1DJ62juBm+/coBInn4VVOg5Cw= +cloud.google.com/go/bigquery v1.72.0/go.mod h1:GUbRtmeCckOE85endLherHD9RsujY+gS7i++c1CqssQ= cloud.google.com/go/bigtable v1.37.0 h1:Q+x7y04lQ0B+WXp03wc1/FLhFt4CwcQdkwWT0M4Jp3w= cloud.google.com/go/bigtable v1.37.0/go.mod h1:HXqddP6hduwzrtiTCqZPpj9ij4hGZb4Zy1WF/dT+yaU= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= @@ -30,6 +34,8 @@ github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNx github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apache/arrow/go/v15 v15.0.2 h1:60IliRbiyTWCWjERBCkO1W4Qun9svcYoZrSLcyOsMLE= +github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= @@ -98,6 +104,8 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -116,6 +124,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -195,6 +205,10 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -232,6 +246,8 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -276,6 +292,8 @@ github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0 github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= @@ -353,9 +371,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= @@ -383,6 +404,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.257.0 h1:8Y0lzvHlZps53PEaw+G29SsQIkuKrumGWs9puiexNAA= diff --git a/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_subscription_test.go b/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_subscription_test.go deleted file mode 100644 index e4e4ee291689..000000000000 --- a/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_subscription_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package bigqueryanalyticshub_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/hashicorp/terraform-provider-google/google/acctest" - "github.com/hashicorp/terraform-provider-google/google/envvar" -) - -func TestAccBigqueryAnalyticsHubListingSubscription_differentProject(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "org_id": envvar.GetTestOrgFromEnv(t), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBigqueryAnalyticsHubListingSubscriptionDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccBigqueryAnalyticsHubListingSubscription_differentProject(context), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing_subscription.subscription", - ImportStateIdFunc: testAccBigqueryAnalyticsHubListingSubscription_stateId, - ImportState: true, - // skipping ImportStateVerify as the resource ID won't match original - // since the user cannot input the project and destination projects simultaneously - }, - }, - }) -} - -func testAccBigqueryAnalyticsHubListingSubscription_stateId(state *terraform.State) (string, error) { - resourceName := "google_bigquery_analytics_hub_listing_subscription.subscription" - var rawState map[string]string - for _, m := range state.Modules { - if len(m.Resources) > 0 { - if v, ok := m.Resources[resourceName]; ok { - rawState = v.Primary.Attributes - } - } - } - - return fmt.Sprintf("projects/%s/locations/US/subscriptions/%s", envvar.GetTestProjectFromEnv(), rawState["subscription_id"]), nil -} - -func testAccBigqueryAnalyticsHubListingSubscription_differentProject(context map[string]interface{}) string { - return acctest.Nprintf(` - - -# Dataset created in default project -resource "google_bigquery_dataset" "subscription" { - dataset_id = "tf_test_my_listing%{random_suffix}" - friendly_name = "tf_test_my_listing%{random_suffix}" - description = "" - location = "US" -} - -resource "google_project" "project" { - project_id = "tf-test-%{random_suffix}" - name = "tf-test-%{random_suffix}" - org_id = "%{org_id}" - deletion_policy = "DELETE" -} - - -resource "google_project_service" "analyticshub" { - project = google_project.project.project_id - service = "analyticshub.googleapis.com" -} - -resource "google_bigquery_analytics_hub_data_exchange" "subscription" { - project = google_project.project.project_id - location = "US" - data_exchange_id = "tf_test_my_data_exchange%{random_suffix}" - display_name = "tf_test_my_data_exchange%{random_suffix}" - description = "" - depends_on = [google_project_service.analyticshub] -} - -resource "google_bigquery_analytics_hub_listing" "subscription" { - project = google_project.project.project_id - location = "US" - data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id - listing_id = "tf_test_my_listing%{random_suffix}" - display_name = "tf_test_my_listing%{random_suffix}" - description = "" - - bigquery_dataset { - dataset = google_bigquery_dataset.subscription.id - } -} - -resource "google_bigquery_analytics_hub_listing_subscription" "subscription" { - project = google_project.project.project_id - location = "US" - data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id - listing_id = google_bigquery_analytics_hub_listing.subscription.listing_id - destination_dataset { - description = "A test subscription" - friendly_name = "👋" - labels = { - testing = "123" - } - location = "US" - dataset_reference { - dataset_id = "tf_test_destination_dataset%{random_suffix}" - project_id = google_bigquery_dataset.subscription.project - } - } -} -`, context) -} diff --git a/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_subscription_test.go.tmpl b/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_subscription_test.go.tmpl new file mode 100644 index 000000000000..74634362815f --- /dev/null +++ b/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_subscription_test.go.tmpl @@ -0,0 +1,188 @@ +package bigqueryanalyticshub_test + +import ( + "fmt" + {{- if ne $.TargetVersionName "ga" }} + "os" + {{- end }} + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +// Always include dummy usages +var _ = fmt.Sprintf +var _ = terraform.State{} +var _ = envvar.GetTestProjectFromEnv +{{- if ne $.TargetVersionName "ga" }} +var _ = os.Getenv +{{- end }} + +func TestAccBigqueryAnalyticsHubListingSubscription_differentProject(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "org_id": envvar.GetTestOrgFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigqueryAnalyticsHubListingSubscriptionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryAnalyticsHubListingSubscription_differentProject(context), + }, + { + ResourceName: "google_bigquery_analytics_hub_listing_subscription.subscription", + ImportStateIdFunc: testAccBigqueryAnalyticsHubListingSubscription_stateId, + ImportState: true, + }, + }, + }) +} + +{{- if ne $.TargetVersionName "ga" }} +func TestAccBigqueryAnalyticsHubListingSubscription_multiregion(t *testing.T) { + if v := os.Getenv("TF_ACC"); v == "" { + t.Skip("Acceptance tests skipped unless env 'TF_ACC' set") + } + + t.Parallel() + + randomDatasetSuffix := acctest.RandString(t, 10) + datasetID := fmt.Sprintf("tf_test_sub_replica_%s", randomDatasetSuffix) + + // BOOTSTRAP: Create multi-region source dataset + bqdataset, err := acctest.AddBigQueryDatasetReplica(envvar.GetTestProjectFromEnv(), datasetID, "us", "eu") + if err != nil { + t.Fatalf("Failed to create BigQuery dataset and add replica: %v", err) + } + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "bqdataset": bqdataset, + } + + t.Cleanup(func() { + acctest.CleanupBigQueryDatasetAndReplica(envvar.GetTestProjectFromEnv(), datasetID, "eu") + }) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigqueryAnalyticsHubListingSubscriptionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryAnalyticsHubListingSubscription_multiregion(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing_subscription.subscription", "destination_dataset.0.replica_locations.#", "1"), + resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing_subscription.subscription", "destination_dataset.0.replica_locations.0", "eu"), + ), + }, + { + ResourceName: "google_bigquery_analytics_hub_listing_subscription.subscription", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"data_exchange_id", "destination_dataset", "listing_id", "location"}, + }, + }, + }) +} +{{- end }} + +func testAccBigqueryAnalyticsHubListingSubscription_stateId(state *terraform.State) (string, error) { + resourceName := "google_bigquery_analytics_hub_listing_subscription.subscription" + var rawState map[string]string + for _, m := range state.Modules { + if len(m.Resources) > 0 { + if v, ok := m.Resources[resourceName]; ok { + rawState = v.Primary.Attributes + } + } + } + + return fmt.Sprintf("projects/%s/locations/US/subscriptions/%s", envvar.GetTestProjectFromEnv(), rawState["subscription_id"]), nil +} + +func testAccBigqueryAnalyticsHubListingSubscription_differentProject(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_bigquery_dataset" "subscription" { + dataset_id = "tf_test_sub_ds_%{random_suffix}" + location = "US" +} + +resource "google_bigquery_analytics_hub_data_exchange" "subscription" { + location = "US" + data_exchange_id = "tf_test_de_%{random_suffix}" + display_name = "tf_test_de_%{random_suffix}" +} + +resource "google_bigquery_analytics_hub_listing" "subscription" { + location = "US" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id + listing_id = "tf_test_listing_%{random_suffix}" + display_name = "tf_test_listing_%{random_suffix}" + + bigquery_dataset { + dataset = google_bigquery_dataset.subscription.id + } +} + +resource "google_bigquery_analytics_hub_listing_subscription" "subscription" { + location = "US" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id + listing_id = google_bigquery_analytics_hub_listing.subscription.listing_id + destination_dataset { + location = "US" + dataset_reference { + dataset_id = "tf_test_dest_ds_%{random_suffix}" + project_id = google_bigquery_dataset.subscription.project + } + } +} +`, context) +} + +{{- if ne $.TargetVersionName "ga" }} +func testAccBigqueryAnalyticsHubListingSubscription_multiregion(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_bigquery_analytics_hub_data_exchange" "subscription" { + location = "us" + data_exchange_id = "tf_test_de_%{random_suffix}" + display_name = "tf_test_de_%{random_suffix}" +} + +resource "google_bigquery_analytics_hub_listing" "subscription" { + location = "us" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id + listing_id = "tf_test_listing_%{random_suffix}" + display_name = "tf_test_listing_%{random_suffix}" + + bigquery_dataset { + dataset = "%{bqdataset}" + replica_locations = ["eu"] + } +} + +resource "google_bigquery_analytics_hub_listing_subscription" "subscription" { + location = "us" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id + listing_id = google_bigquery_analytics_hub_listing.subscription.listing_id + + destination_dataset { + location = "us" + dataset_reference { + project_id = google_bigquery_analytics_hub_data_exchange.subscription.project + dataset_id = "tf_test_sub_dest_ds_%{random_suffix}" + } + replica_locations = ["eu"] + } +} +`, context) +} +{{- end }} diff --git a/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_test.go b/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_test.go deleted file mode 100644 index 29812b24369b..000000000000 --- a/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_test.go +++ /dev/null @@ -1,267 +0,0 @@ -package bigqueryanalyticshub_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingUpdate(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBigqueryAnalyticsHubListingDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingBasicExample(context), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing.listing", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingUpdate(context), - Check: resource.ComposeTestCheckFunc( - // Verify log_linked_dataset_query_user_email has been set to true (at top level) - resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing", "log_linked_dataset_query_user_email", "true"), - ), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing.listing", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccBigqueryAnalyticsHubListing_pubsubListingUpdateConfig(context, `["us-central1"]`, "Example for pubsub topic source - initial"), - Check: resource.ComposeTestCheckFunc( - // Verify initial state for Pub/Sub listing - resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing_pubsub", "pubsub_topic.0.data_affinity_regions.#", "1"), - resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing_pubsub", "pubsub_topic.0.data_affinity_regions.0", "us-central1"), - resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing_pubsub", "description", "Example for pubsub topic source - initial"), - ), - }, - // Step 7: Import the updated Pub/Sub Topic listing to verify import after update. - { - ResourceName: "google_bigquery_analytics_hub_listing.listing_pubsub", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingUpdate(context map[string]interface{}) string { - return acctest.Nprintf(` -resource "google_bigquery_analytics_hub_data_exchange" "listing" { - location = "US" - data_exchange_id = "tf_test_my_data_exchange%{random_suffix}" - display_name = "tf_test_my_data_exchange%{random_suffix}" - description = "example data exchange%{random_suffix}" -} - -resource "google_bigquery_analytics_hub_listing" "listing" { - location = "US" - data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing.data_exchange_id - listing_id = "tf_test_my_listing%{random_suffix}" - display_name = "tf_test_my_listing%{random_suffix}" - description = "example data exchange update%{random_suffix}" - log_linked_dataset_query_user_email = true - - bigquery_dataset { - dataset = google_bigquery_dataset.listing.id - } -} - -resource "google_bigquery_dataset" "listing" { - dataset_id = "tf_test_my_listing%{random_suffix}" - friendly_name = "tf_test_my_listing%{random_suffix}" - description = "example data exchange%{random_suffix}" - location = "US" -} -`, context) -} -func testAccBigqueryAnalyticsHubListing_pubsubListingUpdateConfig(context map[string]interface{}, dataAffinityRegionsHCL string, description string) string { - // Create a mutable copy of the context map - updatedContext := make(map[string]interface{}) - for k, v := range context { - updatedContext[k] = v - } - - // Directly assign the HCL string for data_affinity_regions and the description. - // dataAffinityRegionsHCL will be something like `["us-central1"]` or `["us-central1", "europe-west1"]` - updatedContext["data_affinity_regions_hcl"] = dataAffinityRegionsHCL - updatedContext["description_hcl"] = description - - return acctest.Nprintf(` -# Separate Data Exchange for the Pub/Sub listing to prevent conflicts -resource "google_bigquery_analytics_hub_data_exchange" "listing_pubsub" { - location = "US" - data_exchange_id = "tf_test_pubsub_data_exchange_update_%{random_suffix}" - display_name = "tf_test_pubsub_data_exchange_update_%{random_suffix}" - description = "Example for pubsub topic source - data exchange%{random_suffix}" -} - -# Pub/Sub Topic used as the source for the listing -resource "google_pubsub_topic" "tf_test_pubsub_topic" { - name = "tf_test_test_pubsub_update_%{random_suffix}" -} - -# BigQuery Analytics Hub Listing sourced from the Pub/Sub Topic -resource "google_bigquery_analytics_hub_listing" "listing_pubsub" { - location = "US" - data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing_pubsub.data_exchange_id - listing_id = "tf_test_pubsub_listing_update_%{random_suffix}" - display_name = "tf_test_pubsub_listing_update_%{random_suffix}" - description = "%{description_hcl}" - primary_contact = "test_pubsub_contact@example.com" - - pubsub_topic { - topic = google_pubsub_topic.tf_test_pubsub_topic.id - data_affinity_regions = %{data_affinity_regions_hcl} - } -} -`, updatedContext) -} - -func TestAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingMarketplaceUpdate(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBigqueryAnalyticsHubListingDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingMarketplaceExample(context), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing.listing", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"data_exchange_id", "listing_id", "location", "delete_commercial"}, - }, - { - Config: testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingMarketplaceUpdate(context), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing", "delete_commercial", "false"), - ), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing.listing", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"data_exchange_id", "listing_id", "location", "delete_commercial"}, - }, - }, - }) -} - -func testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingMarketplaceUpdate(context map[string]interface{}) string { - return acctest.Nprintf(` -resource "google_bigquery_analytics_hub_data_exchange" "listing" { - location = "US" - data_exchange_id = "tf_test_my_data_exchange%{random_suffix}" - display_name = "tf_test_my_data_exchange%{random_suffix}" - description = "example data exchange%{random_suffix}" -} - -resource "google_bigquery_analytics_hub_listing" "listing" { - location = "US" - data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing.data_exchange_id - listing_id = "tf_test_my_listing%{random_suffix}" - display_name = "tf_test_my_listing%{random_suffix}" - description = "example data exchange%{random_suffix}" - delete_commercial = false - - bigquery_dataset { - dataset = google_bigquery_dataset.listing.id - } -} - -resource "google_bigquery_dataset" "listing" { - dataset_id = "tf_test_my_listing%{random_suffix}" - friendly_name = "tf_test_my_listing%{random_suffix}" - description = "example data exchange%{random_suffix}" - location = "US" -} -`, context) -} - -func TestAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubPublicListingUpdate(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBigqueryAnalyticsHubListingDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubPublicListingExample(context), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing.listing", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"data_exchange_id", "listing_id", "location"}, - }, - { - Config: testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubPublicListingUpdate(context), - }, - { - ResourceName: "google_bigquery_analytics_hub_listing.listing", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"data_exchange_id", "listing_id", "location"}, - }, - }, - }) -} - -func testAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubPublicListingUpdate(context map[string]interface{}) string { - return acctest.Nprintf(` -resource "google_bigquery_analytics_hub_data_exchange" "listing" { - location = "US" - data_exchange_id = "tf_test_my_data_exchange%{random_suffix}" - display_name = "tf_test_my_data_exchange%{random_suffix}" - description = "example public listing%{random_suffix}" - discovery_type = "DISCOVERY_TYPE_PRIVATE" -} - -resource "google_bigquery_analytics_hub_listing" "listing" { - location = "US" - data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing.data_exchange_id - listing_id = "tf_test_my_listing%{random_suffix}" - display_name = "tf_test_my_listing%{random_suffix}" - description = "example public listing%{random_suffix}" - discovery_type = "DISCOVERY_TYPE_PRIVATE" - allow_only_metadata_sharing= false - - bigquery_dataset { - dataset = google_bigquery_dataset.listing.id - } -} - -resource "google_bigquery_dataset" "listing" { - dataset_id = "tf_test_my_listing%{random_suffix}" - friendly_name = "tf_test_my_listing%{random_suffix}" - description = "example public listing%{random_suffix}" - location = "US" -} -`, context) -} diff --git a/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_test.go.tmpl b/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_test.go.tmpl new file mode 100644 index 000000000000..c383d6492bd9 --- /dev/null +++ b/mmv1/third_party/terraform/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_listing_test.go.tmpl @@ -0,0 +1,178 @@ +package bigqueryanalyticshub_test + +import ( + {{- if ne $.TargetVersionName "ga" }} + "fmt" + "os" + {{- end }} + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +// Dummy usages to ensure imports are satisfied in both versions +var _ = envvar.GetTestProjectFromEnv +{{- if ne $.TargetVersionName "ga" }} +var _ = fmt.Sprintf +var _ = os.Getenv +{{- end }} + +func TestAccBigqueryAnalyticsHubListing_bigqueryAnalyticshubListingUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigqueryAnalyticsHubListingDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryAnalyticsHubListing_basic(context), + }, + { + ResourceName: "google_bigquery_analytics_hub_listing.listing", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBigqueryAnalyticsHubListing_update(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing", "log_linked_dataset_query_user_email", "true"), + ), + }, + }, + }) +} + +{{- if ne $.TargetVersionName "ga" }} +func TestAccBigqueryAnalyticsHubListing_multiregion(t *testing.T) { + // Skip if not running in a acc test environment as BQ DDL bootstrapping is required + if v := os.Getenv("TF_ACC"); v == "" { + t.Skip("Acceptance tests skipped unless env 'TF_ACC' set") + } + + t.Parallel() + + randomDatasetSuffix := acctest.RandString(t, 10) + datasetID := fmt.Sprintf("tf_test_listing_replica_%s", randomDatasetSuffix) + + // BOOTSTRAP: Create dataset and replica via Go client (Terraform cannot create replicas on existing datasets) + bqdataset, err := acctest.AddBigQueryDatasetReplica(envvar.GetTestProjectFromEnv(), datasetID, "us", "eu") + if err != nil { + t.Fatalf("Failed to create BigQuery dataset and add replica: %v", err) + } + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "bqdataset": bqdataset, + } + + // CLEANUP: Ensure the bootstrapped resources are deleted + t.Cleanup(func() { + acctest.CleanupBigQueryDatasetAndReplica(envvar.GetTestProjectFromEnv(), datasetID, "eu") + }) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigqueryAnalyticsHubListingDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryAnalyticsHubListing_multiregion(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing", "bigquery_dataset.0.replica_locations.#", "1"), + resource.TestCheckResourceAttr("google_bigquery_analytics_hub_listing.listing", "bigquery_dataset.0.replica_locations.0", "eu"), + ), + }, + { + ResourceName: "google_bigquery_analytics_hub_listing.listing", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"data_exchange_id", "listing_id", "location"}, + }, + }, + }) +} +{{- end }} + +func testAccBigqueryAnalyticsHubListing_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_bigquery_analytics_hub_data_exchange" "listing" { + location = "US" + data_exchange_id = "tf_test_de_%{random_suffix}" + display_name = "tf_test_de_%{random_suffix}" +} + +resource "google_bigquery_analytics_hub_listing" "listing" { + location = "US" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing.data_exchange_id + listing_id = "tf_test_listing_%{random_suffix}" + display_name = "tf_test_listing_%{random_suffix}" + + bigquery_dataset { + dataset = google_bigquery_dataset.listing.id + } +} + +resource "google_bigquery_dataset" "listing" { + dataset_id = "tf_test_ds_%{random_suffix}" + location = "US" +} +`, context) +} + +func testAccBigqueryAnalyticsHubListing_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_bigquery_analytics_hub_data_exchange" "listing" { + location = "US" + data_exchange_id = "tf_test_de_%{random_suffix}" + display_name = "tf_test_de_%{random_suffix}" +} + +resource "google_bigquery_analytics_hub_listing" "listing" { + location = "US" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing.data_exchange_id + listing_id = "tf_test_listing_%{random_suffix}" + display_name = "tf_test_listing_%{random_suffix}" + log_linked_dataset_query_user_email = true + + bigquery_dataset { + dataset = google_bigquery_dataset.listing.id + } +} + +resource "google_bigquery_dataset" "listing" { + dataset_id = "tf_test_ds_%{random_suffix}" + location = "US" +} +`, context) +} + +{{- if ne $.TargetVersionName "ga" }} +func testAccBigqueryAnalyticsHubListing_multiregion(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_bigquery_analytics_hub_data_exchange" "listing" { + location = "us" + data_exchange_id = "tf_test_de_%{random_suffix}" + display_name = "tf_test_de_%{random_suffix}" +} + +resource "google_bigquery_analytics_hub_listing" "listing" { + location = "us" + data_exchange_id = google_bigquery_analytics_hub_data_exchange.listing.data_exchange_id + listing_id = "tf_test_listing_%{random_suffix}" + display_name = "tf_test_listing_%{random_suffix}" + + bigquery_dataset { + dataset = "%{bqdataset}" + replica_locations = ["eu"] + } +} +`, context) +} +{{- end }} diff --git a/mmv1/third_party/terraform/tpgresource/common_diff_suppress.go b/mmv1/third_party/terraform/tpgresource/common_diff_suppress.go index a0ba73cd1a4e..8911b6fe908e 100644 --- a/mmv1/third_party/terraform/tpgresource/common_diff_suppress.go +++ b/mmv1/third_party/terraform/tpgresource/common_diff_suppress.go @@ -157,3 +157,9 @@ func Base64DiffSuppress(_, old, new string, _ *schema.ResourceData) bool { normalizedNew := r.Replace(new) return normalizedOld == normalizedNew } + +// CaseInsensitiveHash produces the same hash for strings that differ only in case. +// This is used for Set fields where case should not trigger a diff. +func CaseInsensitiveHash(v interface{}) int { + return Hashcode(strings.ToLower(v.(string))) +}