Skip to content

Commit a54663d

Browse files
add project_number field to featureview (#10857) (#18637)
[upstream:baa571435805ea0fa62fce56aad5230a8533d71f] Signed-off-by: Modular Magician <[email protected]>
1 parent 7ea815e commit a54663d

4 files changed

+350
-0
lines changed

.changelog/10857.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
vertexai: added `project_number` field to `google_vertex_ai_feature_online_store_featureview` resource
3+
```

google/services/vertexai/resource_vertex_ai_feature_online_store_featureview.go

+22
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ func ResourceVertexAIFeatureOnlineStoreFeatureview() *schema.Resource {
120120
},
121121
},
122122
},
123+
"project_number": {
124+
Type: schema.TypeString,
125+
Optional: true,
126+
Description: `The project number of the parent project of the feature Groups.`,
127+
},
123128
},
124129
},
125130
ConflictsWith: []string{},
@@ -613,6 +618,8 @@ func flattenVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySource(v interfa
613618
transformed := make(map[string]interface{})
614619
transformed["feature_groups"] =
615620
flattenVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceFeatureGroups(original["featureGroups"], d, config)
621+
transformed["project_number"] =
622+
flattenVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceProjectNumber(original["projectNumber"], d, config)
616623
return []interface{}{transformed}
617624
}
618625
func flattenVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceFeatureGroups(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
@@ -642,6 +649,10 @@ func flattenVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceFeatureGro
642649
return v
643650
}
644651

652+
func flattenVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceProjectNumber(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
653+
return d.Get("feature_registry_source.0.project_number")
654+
}
655+
645656
func flattenVertexAIFeatureOnlineStoreFeatureviewTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
646657
if v == nil {
647658
return v
@@ -734,6 +745,13 @@ func expandVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySource(v interfac
734745
transformed["featureGroups"] = transformedFeatureGroups
735746
}
736747

748+
transformedProjectNumber, err := expandVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceProjectNumber(original["project_number"], d, config)
749+
if err != nil {
750+
return nil, err
751+
} else if val := reflect.ValueOf(transformedProjectNumber); val.IsValid() && !tpgresource.IsEmptyValue(val) {
752+
transformed["projectNumber"] = transformedProjectNumber
753+
}
754+
737755
return transformed, nil
738756
}
739757

@@ -774,6 +792,10 @@ func expandVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceFeatureGrou
774792
return v, nil
775793
}
776794

795+
func expandVertexAIFeatureOnlineStoreFeatureviewFeatureRegistrySourceProjectNumber(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
796+
return v, nil
797+
}
798+
777799
func expandVertexAIFeatureOnlineStoreFeatureviewEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
778800
if v == nil {
779801
return map[string]string{}, nil

google/services/vertexai/resource_vertex_ai_feature_online_store_featureview_generated_test.go

+176
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
2727

2828
"github.com/hashicorp/terraform-provider-google/google/acctest"
29+
"github.com/hashicorp/terraform-provider-google/google/envvar"
2930
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
3031
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
3132
)
@@ -251,6 +252,181 @@ resource "google_vertex_ai_feature_online_store_featureview" "featureview_featur
251252
`, context)
252253
}
253254

255+
func TestAccVertexAIFeatureOnlineStoreFeatureview_vertexAiFeatureonlinestoreFeatureviewCrossProjectExample(t *testing.T) {
256+
t.Parallel()
257+
258+
context := map[string]interface{}{
259+
"billing_account": envvar.GetTestBillingAccountFromEnv(t),
260+
"org_id": envvar.GetTestOrgFromEnv(t),
261+
"random_suffix": acctest.RandString(t, 10),
262+
}
263+
264+
acctest.VcrTest(t, resource.TestCase{
265+
PreCheck: func() { acctest.AccTestPreCheck(t) },
266+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
267+
ExternalProviders: map[string]resource.ExternalProvider{
268+
"time": {},
269+
},
270+
CheckDestroy: testAccCheckVertexAIFeatureOnlineStoreFeatureviewDestroyProducer(t),
271+
Steps: []resource.TestStep{
272+
{
273+
Config: testAccVertexAIFeatureOnlineStoreFeatureview_vertexAiFeatureonlinestoreFeatureviewCrossProjectExample(context),
274+
},
275+
{
276+
ResourceName: "google_vertex_ai_feature_online_store_featureview.cross_project_featureview",
277+
ImportState: true,
278+
ImportStateVerify: true,
279+
ImportStateVerifyIgnore: []string{"feature_online_store", "feature_registry_source.0.project_number", "labels", "name", "region", "terraform_labels"},
280+
},
281+
},
282+
})
283+
}
284+
285+
func testAccVertexAIFeatureOnlineStoreFeatureview_vertexAiFeatureonlinestoreFeatureviewCrossProjectExample(context map[string]interface{}) string {
286+
return acctest.Nprintf(`
287+
data "google_project" "test_project" {
288+
}
289+
290+
resource "google_project" "project" {
291+
project_id = "tf-test%{random_suffix}"
292+
name = "tf-test%{random_suffix}"
293+
org_id = "%{org_id}"
294+
billing_account = "%{billing_account}"
295+
}
296+
297+
resource "time_sleep" "wait_60_seconds" {
298+
depends_on = [google_project.project]
299+
300+
create_duration = "60s"
301+
}
302+
303+
resource "time_sleep" "wait_30_seconds" {
304+
depends_on = [google_bigquery_dataset_iam_member.viewer]
305+
306+
create_duration = "30s"
307+
}
308+
309+
resource "google_project_service" "vertexai" {
310+
service = "aiplatform.googleapis.com"
311+
project = google_project.project.project_id
312+
timeouts {
313+
create = "30m"
314+
update = "40m"
315+
}
316+
disable_on_destroy = false
317+
# Needed for CI tests for permissions to propagate, should not be needed for actual usage
318+
depends_on = [time_sleep.wait_60_seconds]
319+
}
320+
321+
resource "google_bigquery_dataset_iam_member" "viewer" {
322+
project = data.google_project.test_project.project_id
323+
dataset_id = google_bigquery_dataset.sample_dataset.dataset_id
324+
role = "roles/bigquery.dataViewer"
325+
member = "serviceAccount:service-${google_project.project.number}@gcp-sa-aiplatform.iam.gserviceaccount.com"
326+
depends_on = [google_vertex_ai_feature_online_store.featureonlinestore]
327+
}
328+
329+
resource "google_vertex_ai_feature_online_store" "featureonlinestore" {
330+
name = "tf_test_example_cross_project_featureview%{random_suffix}"
331+
project = google_project.project.project_id
332+
labels = {
333+
foo = "bar"
334+
}
335+
region = "us-central1"
336+
bigtable {
337+
auto_scaling {
338+
min_node_count = 1
339+
max_node_count = 2
340+
cpu_utilization_target = 80
341+
}
342+
}
343+
depends_on = [google_project_service.vertexai]
344+
}
345+
346+
resource "google_bigquery_dataset" "sample_dataset" {
347+
dataset_id = "tf_test_example_cross_project_featureview%{random_suffix}"
348+
friendly_name = "test"
349+
description = "This is a test description"
350+
location = "US"
351+
}
352+
353+
resource "google_bigquery_table" "sample_table" {
354+
deletion_protection = false
355+
dataset_id = google_bigquery_dataset.sample_dataset.dataset_id
356+
table_id = "tf_test_example_cross_project_featureview%{random_suffix}"
357+
358+
schema = <<EOF
359+
[
360+
{
361+
"name": "feature_id",
362+
"type": "STRING",
363+
"mode": "NULLABLE"
364+
},
365+
{
366+
"name": "tf_test_example_cross_project_featureview%{random_suffix}",
367+
"type": "STRING",
368+
"mode": "NULLABLE"
369+
},
370+
{
371+
"name": "feature_timestamp",
372+
"type": "TIMESTAMP",
373+
"mode": "NULLABLE"
374+
}
375+
]
376+
EOF
377+
}
378+
379+
resource "google_vertex_ai_feature_group" "sample_feature_group" {
380+
name = "tf_test_example_cross_project_featureview%{random_suffix}"
381+
description = "A sample feature group"
382+
region = "us-central1"
383+
labels = {
384+
label-one = "value-one"
385+
}
386+
big_query {
387+
big_query_source {
388+
# The source table must have a column named 'feature_timestamp' of type TIMESTAMP.
389+
input_uri = "bq://${google_bigquery_table.sample_table.project}.${google_bigquery_table.sample_table.dataset_id}.${google_bigquery_table.sample_table.table_id}"
390+
}
391+
entity_id_columns = ["feature_id"]
392+
}
393+
}
394+
395+
396+
397+
resource "google_vertex_ai_feature_group_feature" "sample_feature" {
398+
name = "tf_test_example_cross_project_featureview%{random_suffix}"
399+
region = "us-central1"
400+
feature_group = google_vertex_ai_feature_group.sample_feature_group.name
401+
description = "A sample feature"
402+
labels = {
403+
label-one = "value-one"
404+
}
405+
}
406+
407+
408+
resource "google_vertex_ai_feature_online_store_featureview" "cross_project_featureview" {
409+
name = "tf_test_example_cross_project_featureview%{random_suffix}"
410+
project = google_project.project.project_id
411+
region = "us-central1"
412+
feature_online_store = google_vertex_ai_feature_online_store.featureonlinestore.name
413+
sync_config {
414+
cron = "0 0 * * *"
415+
}
416+
feature_registry_source {
417+
418+
feature_groups {
419+
feature_group_id = google_vertex_ai_feature_group.sample_feature_group.name
420+
feature_ids = [google_vertex_ai_feature_group_feature.sample_feature.name]
421+
}
422+
project_number = data.google_project.test_project.number
423+
424+
}
425+
depends_on = [google_project_service.vertexai, time_sleep.wait_30_seconds]
426+
}
427+
`, context)
428+
}
429+
254430
func testAccCheckVertexAIFeatureOnlineStoreFeatureviewDestroyProducer(t *testing.T) func(s *terraform.State) error {
255431
return func(s *terraform.State) error {
256432
for name, rs := range s.RootModule().Resources {

0 commit comments

Comments
 (0)