diff --git a/mmv1/products/vertexai/FeatureOnlineStore.yaml b/mmv1/products/vertexai/FeatureOnlineStore.yaml new file mode 100644 index 000000000000..de3cb1558f08 --- /dev/null +++ b/mmv1/products/vertexai/FeatureOnlineStore.yaml @@ -0,0 +1,226 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: FeatureOnlineStore +base_url: projects/{{project}}/locations/{{region}}/featureOnlineStores +create_url: projects/{{project}}/locations/{{region}}/featureOnlineStores?featureOnlineStoreId={{name}} +self_link: 'projects/{{project}}/locations/{{region}}/featureOnlineStores/{{name}}' +update_verb: :PATCH +update_mask: true +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/vertex-ai/docs' + api: 'https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.featureOnlineStores' +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: 'name' + base_url: '{{op_id}}' + wait_ms: 1000 + result: !ruby/object:Api::OpAsync::Result + path: 'response' + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: 'done' + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: 'error' + message: 'message' +description: |- + A collection of DataItems and Annotations on them. +autogen_async: false +skip_sweeper: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'vertex_ai_featureonlinestore_with_beta_fields_optimized' + primary_resource_id: 'featureonlinestore' + primary_resource_name: "fmt.Sprintf(\"terraform%s\", + context[\"random_suffix\"\ + ])" + vars: + name: 'terraform' + project: 'appeng-flex' + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + ignore_read_extra: + - 'force_destroy' + min_version: beta + - !ruby/object:Provider::Terraform::Examples + name: 'vertex_ai_featureonlinestore_with_bigtable' + primary_resource_id: 'featureonlinestore' + primary_resource_name: "fmt.Sprintf(\"terraform%s\", + context[\"random_suffix\"\ + ])" + vars: + name: 'terraform2' + project: 'appeng-flex' + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + ignore_read_extra: + - 'force_destroy' + - !ruby/object:Provider::Terraform::Examples + name: 'vertex_ai_featureonlinestore_with_beta_fields_bigtable' + primary_resource_id: 'featureonlinestore' + primary_resource_name: "fmt.Sprintf(\"terraform%s\", + context[\"random_suffix\"\ + ])" + vars: + name: 'terraform3' + project: 'appeng-flex' + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + ignore_read_extra: + - 'force_destroy' + min_version: beta +custom_code: !ruby/object:Provider::Terraform::CustomCode + pre_delete: templates/terraform/pre_delete/vertex_ai_force_delete.go.erb +virtual_fields: + - !ruby/object:Api::Type::Boolean + name: 'force_destroy' + description: + 'If set to true, any FeatureViews and Features for this FeatureOnlineStore will also be deleted.' + default_value: false +parameters: + - !ruby/object:Api::Type::String + name: region + description: The region of the dataset. eg us-central1 + url_param_only: true + immutable: true + default_from_api: true +properties: + - !ruby/object:Api::Type::String + name: 'name' + description: + The name of the FeatureOnlinestore. This value may be up to 60 characters, and + valid characters are [a-z0-9_]. The first character cannot be a number. + immutable: true + url_param_only: true + pattern: projects/{{project}}/locations/{{region}}/featureOnlineStores/{{name}} + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + - !ruby/object:Api::Type::String + name: 'etag' + description: Used to perform consistent read-modify-write updates. + output: true + ignore_read: true + - !ruby/object:Api::Type::String + name: 'createTime' + output: true + description: | + The timestamp of when the featurestore was created in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. + - !ruby/object:Api::Type::String + name: 'updateTime' + output: true + description: | + The timestamp of when the featurestore was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' + description: | + A set of key/value label pairs to assign to this Featurestore. + - !ruby/object:Api::Type::NestedObject + name: 'dedicatedServingEndpoint' + description: | + The dedicated serving endpoint for this FeatureOnlineStore, which is different from common vertex service endpoint. + min_version: beta + default_from_api: true + properties: + - !ruby/object:Api::Type::String + name: 'publicEndpointDomainName' + description: | + populated with the domain name to use for this FeatureOnlineStore + output: true + - !ruby/object:Api::Type::String + name: 'serviceAttachment' + description: | + name of the service attachment resource. Populated if private service connect is enabled and after FeatureViewSync is created. + output: true + - !ruby/object:Api::Type::NestedObject + name: 'privateServiceConnectConfig' + description: | + Private service connect config. + default_from_api: true + properties: + - !ruby/object:Api::Type::Boolean + name: 'enablePrivateServiceConnect' + required: true + default_from_api: true + description: | + If set to true, customers will use private service connection to send request. Otherwise, the connection will set to public endpoint. + - !ruby/object:Api::Type::Array + name: 'projectAllowlist' + required: true + default_from_api: true + description: | + A list of Projects from which the forwarding rule will target the service attachment. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'embeddingManagement' + description: | + The settings for embedding management in FeatureOnlineStore. Embedding management can only be used with BigTable. + min_version: beta + properties: + - !ruby/object:Api::Type::Boolean + name: 'enabled' + description: | + Enable embedding management. + immutable: true + - !ruby/object:Api::Type::NestedObject + name: 'bigtable' + description: | + Contains settings for the Cloud Bigtable instance that will be created to serve featureValues for all FeatureViews under this FeatureOnlineStore. + conflicts: + - optimized + exactly_one_of: + - bigtable + - optimized + properties: + - !ruby/object:Api::Type::NestedObject + name: 'autoScaling' + required: true + description: | + Autoscaling config applied to Bigtable Instance. + properties: + - !ruby/object:Api::Type::Integer + name: 'minNodeCount' + required: true + description: | + The minimum number of nodes to scale down to. Must be greater than or equal to 1. + - !ruby/object:Api::Type::Integer + name: 'maxNodeCount' + required: true + description: | + The maximum number of nodes to scale up to. Must be greater than minNodeCount, and less than or equal to 10 times of 'minNodeCount'. + - !ruby/object:Api::Type::Integer + name: 'cpuUtilizationTarget' + description: | + A percentage of the cluster's CPU capacity. Can be from 10% to 80%. When a cluster's CPU utilization exceeds the target that you have set, Bigtable immediately adds nodes to the cluster. When CPU utilization is substantially lower than the target, Bigtable removes nodes. If not set will default to 50%. + - !ruby/object:Api::Type::NestedObject + name: 'optimized' + description: + Contains settings for the Optimized store that will be created to serve featureValues for all FeatureViews under this FeatureOnlineStore + conflicts: + - bigtable + exactly_one_of: + - bigtable + - optimized + min_version: beta + properties: + [] # Meant to be an empty object with no properties - see here : https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.featureOnlineStores#Optimized + # The fields below are necessary to include the "Optimized" transformation in the payload + send_empty_value: true + allow_empty_object: true \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_beta_fields_bigtable.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_beta_fields_bigtable.tf.erb new file mode 100644 index 000000000000..fbfdc11663fd --- /dev/null +++ b/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_beta_fields_bigtable.tf.erb @@ -0,0 +1,28 @@ +resource "google_vertex_ai_feature_online_store" "<%= ctx[:primary_resource_id] %>" { + provider = "google-beta" + name = "<%= ctx[:vars]['name'] %>" + labels = { + foo = "bar" + } + region = "us-central1" + bigtable { + auto_scaling { + min_node_count = 1 + max_node_count = 2 + cpu_utilization_target = 80 + } +} +embedding_management { + enabled = true + } + dedicated_serving_endpoint { + private_service_connect_config { + enable_private_service_connect = true + project_allowlist = [data.google_project.project.number] + } +} + force_destroy = true +} + +data "google_project" "project" {} + diff --git a/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_beta_fields_optimized.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_beta_fields_optimized.tf.erb new file mode 100644 index 000000000000..b93099a75b51 --- /dev/null +++ b/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_beta_fields_optimized.tf.erb @@ -0,0 +1,20 @@ +resource "google_vertex_ai_feature_online_store" "<%= ctx[:primary_resource_id] %>" { + provider = "google-beta" + name = "<%= ctx[:vars]['name'] %>" + labels = { + foo = "bar" + } + region = "us-central1" + optimized {} + dedicated_serving_endpoint { + private_service_connect_config { + enable_private_service_connect = true + project_allowlist = [data.google_project.project.number] + } + } + force_destroy = true +} + +data "google_project" "project" {} + + diff --git a/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_bigtable.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_bigtable.tf.erb new file mode 100644 index 000000000000..a42b69f4c081 --- /dev/null +++ b/mmv1/templates/terraform/examples/vertex_ai_featureonlinestore_with_bigtable.tf.erb @@ -0,0 +1,16 @@ +##FeatureOnlineStore With BigTable +resource "google_vertex_ai_feature_online_store" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + labels = { + foo = "bar" + } + region = "us-central1" + bigtable { + auto_scaling { + min_node_count = 1 + max_node_count = 3 + cpu_utilization_target = 50 + } + } + force_destroy = true +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_feature_online_store_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_feature_online_store_test.go new file mode 100644 index 000000000000..b40dd2be2832 --- /dev/null +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_feature_online_store_test.go @@ -0,0 +1,88 @@ +package vertexai_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccVertexAIFeatureOnlineStore_vertexAiFeatureonlinestoreWithBigtable_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccVertexAIFeatureOnlineStore_vertexAiFeatureonlinestoreWithBigtable_basic(context), + }, + resource.TestStep{ + ResourceName: "google_vertex_ai_feature_online_store.featureonlinestore_bigtable", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "etag", "region", "force_destroy", "labels", "terraform_labels"}, + }, + resource.TestStep{ + Config: testAccVertexAIFeatureOnlineStore_vertexAiFeatureonlinestoreWithBigtableExample_update(context), + }, + resource.TestStep{ + + ResourceName: "google_vertex_ai_feature_online_store.featureonlinestore_bigtable", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "etag", "region", "force_destroy", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccVertexAIFeatureOnlineStore_vertexAiFeatureonlinestoreWithBigtable_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +##FeatureOnlineStore With BigTable +resource "google_vertex_ai_feature_online_store" "featureonlinestore_bigtable" { + name = "terraform2%{random_suffix}" + labels = { + foo = "bar" + } + region = "us-central1" + bigtable { + auto_scaling { + min_node_count = 1 + max_node_count = 3 + cpu_utilization_target = 50 + } + } + force_destroy = true +} +`, context) +} + +func testAccVertexAIFeatureOnlineStore_vertexAiFeatureonlinestoreWithBigtableExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +##FeatureOnlineStore With BigTable +resource "google_vertex_ai_feature_online_store" "featureonlinestore_bigtable" { + name = "terraform2%{random_suffix}" + labels = { + foo1 = "bar1" + } + region = "us-central1" + bigtable { + auto_scaling { + min_node_count = 2 + max_node_count = 4 + cpu_utilization_target = 60 + } + } + force_destroy = true +} +`, context) +} \ No newline at end of file