Skip to content

Commit ec5e6b2

Browse files
c2thornDawid212
authored andcommitted
Fix cross-project listing subscriptions (GoogleCloudPlatform#13362)
1 parent 5a64d7b commit ec5e6b2

File tree

3 files changed

+155
-1
lines changed

3 files changed

+155
-1
lines changed

mmv1/products/bigqueryanalyticshub/ListingSubscription.yaml

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ references:
1919
guides:
2020
'Official Documentation': 'https://cloud.google.com/bigquery/docs/analytics-hub-introduction'
2121
api: 'https://cloud.google.com/bigquery/docs/reference/analytics-hub/rest/v1/projects.locations.subscriptions'
22+
docs:
23+
note: |-
24+
When importing the resource with `terraform import`, provide the destination project and location
25+
in the format projects/{{destination_project}}/locations/{{destination_location}}/subscriptions/{{subscription_id}}
2226
base_url: 'projects/{{project}}/locations/{{location}}/subscriptions'
2327
self_link: 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}'
2428
create_url: 'projects/{{project}}/locations/{{location}}/dataExchanges/{{data_exchange_id}}/listings/{{listing_id}}:subscribe'
@@ -27,6 +31,8 @@ import_format:
2731
- 'projects/{{project}}/locations/{{location}}/subscriptions/{{subscription_id}}'
2832
custom_code:
2933
post_create: templates/terraform/post_create/analytics_hub_subscription.go.tmpl
34+
pre_read: 'templates/terraform/pre_read/bigqueryanalyticshub_listing_subscription.tmpl'
35+
pre_delete: 'templates/terraform/pre_read/bigqueryanalyticshub_listing_subscription.tmpl'
3036
post_import: templates/terraform/post_import/analytics_hub_subscription.go.tmpl
3137
sweeper:
3238
url_substitutions:
@@ -61,7 +67,7 @@ parameters:
6167
- name: 'location'
6268
type: String
6369
description: |
64-
The name of the location for this subscription.
70+
The name of the location of the data exchange. Distinct from the location of the destination data set.
6571
url_param_only: true
6672
required: true
6773
custom_flatten: 'templates/terraform/custom_flatten/bigquery_dataset_location.go.tmpl'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{/*
2+
The license inside this block applies to this file
3+
Copyright 2025 Google Inc.
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/ -}}
13+
// The project used for Create and Read may be different.
14+
// Here, we will use the destination project specifically for reading and deleting.
15+
// This cannot be done editing the self_link since the destination project is not a top-level field.
16+
destinationProject, ok := d.GetOk("destination_dataset.0.dataset_reference.0.project_id")
17+
if ok {
18+
billingProject = destinationProject.(string)
19+
20+
// err == nil indicates that the billing_project value was found
21+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
22+
billingProject = bp
23+
}
24+
destinationLocation := d.Get("destination_dataset.0.location")
25+
partToReplace := regexp.MustCompile(`projects\/.*\/locations\/.*\/subscriptions`)
26+
url = partToReplace.ReplaceAllString(url, fmt.Sprintf("projects/%s/locations/%s/subscriptions", destinationProject, destinationLocation))
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package bigqueryanalyticshub_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-testing/terraform"
9+
"github.com/hashicorp/terraform-provider-google/google/acctest"
10+
"github.com/hashicorp/terraform-provider-google/google/envvar"
11+
)
12+
13+
func TestAccBigqueryAnalyticsHubListingSubscription_differentProject(t *testing.T) {
14+
t.Parallel()
15+
16+
context := map[string]interface{}{
17+
"random_suffix": acctest.RandString(t, 10),
18+
"org_id": envvar.GetTestOrgFromEnv(t),
19+
}
20+
21+
acctest.VcrTest(t, resource.TestCase{
22+
PreCheck: func() { acctest.AccTestPreCheck(t) },
23+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
24+
CheckDestroy: testAccCheckBigqueryAnalyticsHubListingSubscriptionDestroyProducer(t),
25+
Steps: []resource.TestStep{
26+
{
27+
Config: testAccBigqueryAnalyticsHubListingSubscription_differentProject(context),
28+
},
29+
{
30+
ResourceName: "google_bigquery_analytics_hub_listing_subscription.subscription",
31+
ImportStateIdFunc: testAccBigqueryAnalyticsHubListingSubscription_stateId,
32+
ImportState: true,
33+
// skipping ImportStateVerify as the resource ID won't match original
34+
// since the user cannot input the project and destination projects simultaneously
35+
},
36+
},
37+
})
38+
}
39+
40+
func testAccBigqueryAnalyticsHubListingSubscription_stateId(state *terraform.State) (string, error) {
41+
resourceName := "google_bigquery_analytics_hub_listing_subscription.subscription"
42+
var rawState map[string]string
43+
for _, m := range state.Modules {
44+
if len(m.Resources) > 0 {
45+
if v, ok := m.Resources[resourceName]; ok {
46+
rawState = v.Primary.Attributes
47+
}
48+
}
49+
}
50+
51+
return fmt.Sprintf("projects/%s/locations/US/subscriptions/%s", envvar.GetTestProjectFromEnv(), rawState["subscription_id"]), nil
52+
}
53+
54+
func testAccBigqueryAnalyticsHubListingSubscription_differentProject(context map[string]interface{}) string {
55+
return acctest.Nprintf(`
56+
57+
58+
# Dataset created in default project
59+
resource "google_bigquery_dataset" "subscription" {
60+
dataset_id = "tf_test_my_listing%{random_suffix}"
61+
friendly_name = "tf_test_my_listing%{random_suffix}"
62+
description = ""
63+
location = "US"
64+
}
65+
66+
resource "google_project" "project" {
67+
project_id = "tf-test-%{random_suffix}"
68+
name = "tf-test-%{random_suffix}"
69+
org_id = "%{org_id}"
70+
deletion_policy = "DELETE"
71+
}
72+
73+
74+
resource "google_project_service" "analyticshub" {
75+
project = google_project.project.project_id
76+
service = "analyticshub.googleapis.com"
77+
disable_on_destroy = false # Need it enabled in the project when the test disables services in post-test cleanup
78+
}
79+
80+
resource "google_bigquery_analytics_hub_data_exchange" "subscription" {
81+
project = google_project.project.project_id
82+
location = "US"
83+
data_exchange_id = "tf_test_my_data_exchange%{random_suffix}"
84+
display_name = "tf_test_my_data_exchange%{random_suffix}"
85+
description = ""
86+
depends_on = [google_project_service.analyticshub]
87+
}
88+
89+
resource "google_bigquery_analytics_hub_listing" "subscription" {
90+
project = google_project.project.project_id
91+
location = "US"
92+
data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id
93+
listing_id = "tf_test_my_listing%{random_suffix}"
94+
display_name = "tf_test_my_listing%{random_suffix}"
95+
description = ""
96+
97+
bigquery_dataset {
98+
dataset = google_bigquery_dataset.subscription.id
99+
}
100+
}
101+
102+
resource "google_bigquery_analytics_hub_listing_subscription" "subscription" {
103+
project = google_project.project.project_id
104+
location = "US"
105+
data_exchange_id = google_bigquery_analytics_hub_data_exchange.subscription.data_exchange_id
106+
listing_id = google_bigquery_analytics_hub_listing.subscription.listing_id
107+
destination_dataset {
108+
description = "A test subscription"
109+
friendly_name = "👋"
110+
labels = {
111+
testing = "123"
112+
}
113+
location = "US"
114+
dataset_reference {
115+
dataset_id = "tf_test_destination_dataset%{random_suffix}"
116+
project_id = google_bigquery_dataset.subscription.project
117+
}
118+
}
119+
}
120+
`, context)
121+
}

0 commit comments

Comments
 (0)