Skip to content

Commit f757f26

Browse files
committed
New data sources: google_discovery_engine_data_store(s)
Add two handwritten data sources for Discovery Engine data stores: - `google_discovery_engine_data_store`: retrieves a single data store by `data_store_id` or `display_name` (mutually exclusive). Errors if multiple stores share the same display name. - `google_discovery_engine_data_stores`: lists all data stores in a project/location with pagination support. Both default `location` to "global" and inherit `project` from the provider config when not specified. The singular data source reuses the existing resource's flatten helpers.
1 parent 490c3c8 commit f757f26

7 files changed

Lines changed: 530 additions & 0 deletions

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ var handwrittenDatasources = map[string]*schema.Resource{
165165
"google_dataplex_data_quality_rules": dataplex.DataSourceDataplexDataQualityRules(),
166166
"google_dataproc_metastore_service": dataprocmetastore.DataSourceDataprocMetastoreService(),
167167
"google_datastream_static_ips": datastream.DataSourceGoogleDatastreamStaticIps(),
168+
"google_discovery_engine_data_store": discoveryengine.DataSourceGoogleDiscoveryEngineDataStore(),
169+
"google_discovery_engine_data_stores": discoveryengine.DataSourceGoogleDiscoveryEngineDataStores(),
168170
"google_dns_keys": dns.DataSourceDNSKeys(),
169171
"google_dns_managed_zone": dns.DataSourceDnsManagedZone(),
170172
"google_dns_managed_zones": dns.DataSourceDnsManagedZones(),
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package discoveryengine
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
)
12+
13+
func DataSourceGoogleDiscoveryEngineDataStore() *schema.Resource {
14+
dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceDiscoveryEngineDataStore().Schema)
15+
16+
tpgresource.AddOptionalFieldsToSchema(dsSchema, "project", "location", "data_store_id", "display_name")
17+
dsSchema["location"].Default = "global"
18+
19+
return &schema.Resource{
20+
Read: dataSourceGoogleDiscoveryEngineDataStoreRead,
21+
Schema: dsSchema,
22+
}
23+
}
24+
25+
func dataSourceGoogleDiscoveryEngineDataStoreRead(d *schema.ResourceData, meta interface{}) error {
26+
config := meta.(*transport_tpg.Config)
27+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
28+
if err != nil {
29+
return err
30+
}
31+
32+
project, err := tpgresource.GetProject(d, config)
33+
if err != nil {
34+
return fmt.Errorf("Error fetching project for DataStore: %s", err)
35+
}
36+
37+
location := d.Get("location").(string)
38+
39+
billingProject := project
40+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
41+
billingProject = bp
42+
}
43+
44+
dataStoreId, hasId := d.GetOk("data_store_id")
45+
displayName, hasName := d.GetOk("display_name")
46+
47+
if hasId == hasName {
48+
return fmt.Errorf("Exactly one of 'data_store_id' or 'display_name' must be provided")
49+
}
50+
51+
var res map[string]interface{}
52+
53+
if hasId {
54+
url, err := tpgresource.ReplaceVars(d, config, "{{DiscoveryEngineBasePath}}projects/{{project}}/locations/{{location}}/collections/default_collection/dataStores/{{data_store_id}}")
55+
if err != nil {
56+
return err
57+
}
58+
59+
res, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
60+
Config: config,
61+
Method: "GET",
62+
Project: billingProject,
63+
RawURL: url,
64+
UserAgent: userAgent,
65+
})
66+
if err != nil {
67+
return fmt.Errorf("Error reading DataStore %s/%s/%s: %s", project, location, dataStoreId, err)
68+
}
69+
} else {
70+
// List all data stores and filter by display_name
71+
listURL, err := tpgresource.ReplaceVars(d, config, "{{DiscoveryEngineBasePath}}projects/{{project}}/locations/{{location}}/collections/default_collection/dataStores")
72+
if err != nil {
73+
return err
74+
}
75+
76+
var matches []map[string]interface{}
77+
params := make(map[string]string)
78+
79+
for {
80+
pageURL, err := transport_tpg.AddQueryParams(listURL, params)
81+
if err != nil {
82+
return err
83+
}
84+
85+
listRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
86+
Config: config,
87+
Method: "GET",
88+
Project: billingProject,
89+
RawURL: pageURL,
90+
UserAgent: userAgent,
91+
})
92+
if err != nil {
93+
return fmt.Errorf("Error listing DataStores: %s", err)
94+
}
95+
96+
if items, ok := listRes["dataStores"].([]interface{}); ok {
97+
for _, item := range items {
98+
ds := item.(map[string]interface{})
99+
if ds["displayName"] == displayName {
100+
matches = append(matches, ds)
101+
}
102+
}
103+
}
104+
105+
pToken, ok := listRes["nextPageToken"]
106+
if ok && pToken != nil && pToken.(string) != "" {
107+
params["pageToken"] = pToken.(string)
108+
} else {
109+
break
110+
}
111+
}
112+
113+
if len(matches) == 0 {
114+
return fmt.Errorf("No data store found with display name %q in project %q, location %q", displayName, project, location)
115+
}
116+
if len(matches) > 1 {
117+
var ids []string
118+
for _, m := range matches {
119+
ids = append(ids, tpgresource.GetResourceNameFromSelfLink(m["name"].(string)))
120+
}
121+
return fmt.Errorf("Multiple data stores found with display name %q (IDs: %v). Use 'data_store_id' instead", displayName, ids)
122+
}
123+
124+
res = matches[0]
125+
}
126+
127+
resolvedId := tpgresource.GetResourceNameFromSelfLink(res["name"].(string))
128+
129+
if err := d.Set("project", project); err != nil {
130+
return fmt.Errorf("Error reading DataStore: %s", err)
131+
}
132+
if err := d.Set("data_store_id", resolvedId); err != nil {
133+
return fmt.Errorf("Error reading DataStore: %s", err)
134+
}
135+
if err := d.Set("name", flattenDiscoveryEngineDataStoreName(res["name"], d, config)); err != nil {
136+
return fmt.Errorf("Error reading DataStore: %s", err)
137+
}
138+
if err := d.Set("display_name", flattenDiscoveryEngineDataStoreDisplayName(res["displayName"], d, config)); err != nil {
139+
return fmt.Errorf("Error reading DataStore: %s", err)
140+
}
141+
if err := d.Set("industry_vertical", flattenDiscoveryEngineDataStoreIndustryVertical(res["industryVertical"], d, config)); err != nil {
142+
return fmt.Errorf("Error reading DataStore: %s", err)
143+
}
144+
if err := d.Set("solution_types", flattenDiscoveryEngineDataStoreSolutionTypes(res["solutionTypes"], d, config)); err != nil {
145+
return fmt.Errorf("Error reading DataStore: %s", err)
146+
}
147+
if err := d.Set("default_schema_id", flattenDiscoveryEngineDataStoreDefaultSchemaId(res["defaultSchemaId"], d, config)); err != nil {
148+
return fmt.Errorf("Error reading DataStore: %s", err)
149+
}
150+
if err := d.Set("content_config", flattenDiscoveryEngineDataStoreContentConfig(res["contentConfig"], d, config)); err != nil {
151+
return fmt.Errorf("Error reading DataStore: %s", err)
152+
}
153+
if err := d.Set("create_time", flattenDiscoveryEngineDataStoreCreateTime(res["createTime"], d, config)); err != nil {
154+
return fmt.Errorf("Error reading DataStore: %s", err)
155+
}
156+
157+
d.SetId(fmt.Sprintf("projects/%s/locations/%s/collections/default_collection/dataStores/%s", project, location, resolvedId))
158+
159+
return nil
160+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package discoveryengine_test
4+
5+
import (
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
9+
"github.com/hashicorp/terraform-provider-google/google/acctest"
10+
)
11+
12+
func TestAccDataSourceGoogleDiscoveryEngineDataStore_basic(t *testing.T) {
13+
t.Parallel()
14+
15+
context := map[string]interface{}{
16+
"random_suffix": acctest.RandString(t, 10),
17+
}
18+
19+
acctest.VcrTest(t, resource.TestCase{
20+
PreCheck: func() { acctest.AccTestPreCheck(t) },
21+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
22+
CheckDestroy: testAccCheckDiscoveryEngineDataStoreDestroyProducer(t),
23+
Steps: []resource.TestStep{
24+
{
25+
Config: testAccDataSourceGoogleDiscoveryEngineDataStore_basic(context),
26+
Check: resource.ComposeTestCheckFunc(
27+
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(
28+
"data.google_discovery_engine_data_store.ds",
29+
"google_discovery_engine_data_store.res",
30+
[]string{
31+
"create_advanced_site_search",
32+
"skip_default_schema_creation",
33+
},
34+
),
35+
),
36+
},
37+
},
38+
})
39+
}
40+
41+
func testAccDataSourceGoogleDiscoveryEngineDataStore_basic(context map[string]interface{}) string {
42+
return acctest.Nprintf(`
43+
resource "google_discovery_engine_data_store" "res" {
44+
location = "global"
45+
data_store_id = "tf-test-ds-id%{random_suffix}"
46+
display_name = "tf-test-ds-datasource"
47+
industry_vertical = "GENERIC"
48+
content_config = "NO_CONTENT"
49+
solution_types = ["SOLUTION_TYPE_SEARCH"]
50+
create_advanced_site_search = false
51+
skip_default_schema_creation = false
52+
}
53+
54+
data "google_discovery_engine_data_store" "ds" {
55+
location = google_discovery_engine_data_store.res.location
56+
data_store_id = google_discovery_engine_data_store.res.data_store_id
57+
}
58+
`, context)
59+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package discoveryengine
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
)
12+
13+
func DataSourceGoogleDiscoveryEngineDataStores() *schema.Resource {
14+
return &schema.Resource{
15+
Read: dataSourceGoogleDiscoveryEngineDataStoresRead,
16+
Schema: map[string]*schema.Schema{
17+
"location": {
18+
Type: schema.TypeString,
19+
Optional: true,
20+
Default: "global",
21+
Description: `The geographic location where the data stores reside. The value can only be one of "global", "us" and "eu".`,
22+
},
23+
"project": {
24+
Type: schema.TypeString,
25+
Optional: true,
26+
Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`,
27+
},
28+
"data_stores": {
29+
Type: schema.TypeList,
30+
Computed: true,
31+
Elem: &schema.Resource{
32+
Schema: map[string]*schema.Schema{
33+
"name": {
34+
Type: schema.TypeString,
35+
Computed: true,
36+
},
37+
"data_store_id": {
38+
Type: schema.TypeString,
39+
Computed: true,
40+
},
41+
"display_name": {
42+
Type: schema.TypeString,
43+
Computed: true,
44+
},
45+
"industry_vertical": {
46+
Type: schema.TypeString,
47+
Computed: true,
48+
},
49+
"content_config": {
50+
Type: schema.TypeString,
51+
Computed: true,
52+
},
53+
"solution_types": {
54+
Type: schema.TypeList,
55+
Computed: true,
56+
Elem: &schema.Schema{
57+
Type: schema.TypeString,
58+
},
59+
},
60+
"default_schema_id": {
61+
Type: schema.TypeString,
62+
Computed: true,
63+
},
64+
"create_time": {
65+
Type: schema.TypeString,
66+
Computed: true,
67+
},
68+
},
69+
},
70+
},
71+
},
72+
}
73+
}
74+
75+
func dataSourceGoogleDiscoveryEngineDataStoresRead(d *schema.ResourceData, meta interface{}) error {
76+
config := meta.(*transport_tpg.Config)
77+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
78+
if err != nil {
79+
return err
80+
}
81+
82+
project, err := tpgresource.GetProject(d, config)
83+
if err != nil {
84+
return fmt.Errorf("Error fetching project for DataStores: %s", err)
85+
}
86+
87+
location := d.Get("location").(string)
88+
89+
billingProject := project
90+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
91+
billingProject = bp
92+
}
93+
94+
url, err := tpgresource.ReplaceVars(d, config, "{{DiscoveryEngineBasePath}}projects/{{project}}/locations/{{location}}/collections/default_collection/dataStores")
95+
if err != nil {
96+
return err
97+
}
98+
99+
dataStores := make([]map[string]interface{}, 0)
100+
params := make(map[string]string)
101+
102+
for {
103+
listURL, err := transport_tpg.AddQueryParams(url, params)
104+
if err != nil {
105+
return err
106+
}
107+
108+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
109+
Config: config,
110+
Method: "GET",
111+
Project: billingProject,
112+
RawURL: listURL,
113+
UserAgent: userAgent,
114+
})
115+
if err != nil {
116+
return fmt.Errorf("Error listing DataStores: %s", err)
117+
}
118+
119+
pageDataStores := flattenDiscoveryEngineDataStoresList(res["dataStores"])
120+
dataStores = append(dataStores, pageDataStores...)
121+
122+
pToken, ok := res["nextPageToken"]
123+
if ok && pToken != nil && pToken.(string) != "" {
124+
params["pageToken"] = pToken.(string)
125+
} else {
126+
break
127+
}
128+
}
129+
130+
if err := d.Set("data_stores", dataStores); err != nil {
131+
return fmt.Errorf("Error setting data_stores: %s", err)
132+
}
133+
134+
d.SetId(fmt.Sprintf("projects/%s/locations/%s/dataStores", project, location))
135+
136+
return nil
137+
}
138+
139+
func flattenDiscoveryEngineDataStoresList(v interface{}) []map[string]interface{} {
140+
if v == nil {
141+
return make([]map[string]interface{}, 0)
142+
}
143+
144+
ls := v.([]interface{})
145+
dataStores := make([]map[string]interface{}, 0, len(ls))
146+
for _, raw := range ls {
147+
o := raw.(map[string]interface{})
148+
dataStores = append(dataStores, map[string]interface{}{
149+
"name": o["name"],
150+
"display_name": o["displayName"],
151+
"industry_vertical": o["industryVertical"],
152+
"content_config": o["contentConfig"],
153+
"solution_types": o["solutionTypes"],
154+
"default_schema_id": o["defaultSchemaId"],
155+
"create_time": o["createTime"],
156+
"data_store_id": tpgresource.GetResourceNameFromSelfLink(o["name"].(string)),
157+
})
158+
}
159+
160+
return dataStores
161+
}

0 commit comments

Comments
 (0)