Skip to content

Commit 26748cf

Browse files
mmurakowski-verilyBBBmau
authored andcommitted
Adding missing fields to vertexai.Endpoint resource (GoogleCloudPlatform#12110)
1 parent 13a3196 commit 26748cf

File tree

6 files changed

+158
-46
lines changed

6 files changed

+158
-46
lines changed

mmv1/products/vertexai/Endpoint.yaml

+90-1
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,15 @@ examples:
6363
address_name: 'address-name'
6464
kms_key_name: 'kms-name'
6565
network_name: 'network-name'
66+
dataset_id: 'some_dataset'
6667
# Test is covered by handwritten test to include an update.
6768
exclude_test: true
69+
- name: 'vertex_ai_endpoint_private_service_connect'
70+
primary_resource_id: 'endpoint'
71+
primary_resource_name: 'fmt.Sprintf("endpoint-name%s", context["random_suffix"])'
72+
- name: 'vertex_ai_endpoint_dedicated_endpoint'
73+
primary_resource_id: 'endpoint'
74+
primary_resource_name: 'fmt.Sprintf("endpoint-name%s", context["random_suffix"])'
6875
parameters:
6976
- name: 'location'
7077
type: String
@@ -358,6 +365,22 @@ properties:
358365
`stderr` and `stdout` streams to Stackdriver Logging. Only supported
359366
for custom-trained Models and AutoML Tabular Models.
360367
output: true
368+
- name: 'trafficSplit'
369+
type: String
370+
description: |
371+
A map from a DeployedModel's id to the percentage of this Endpoint's traffic that should be forwarded to that DeployedModel.
372+
If a DeployedModel's id is not listed in this map, then it receives no traffic.
373+
The traffic percentage values must add up to 100, or map must be empty if the Endpoint is to not accept any traffic at a moment.
374+
375+
~> **Note:** The `traffic_split` setting only applies after a model has been deployed to the endpoint. Re-applying a `google_vertex_ai_endpoint`
376+
resource without updating the `traffic_split` post-deployment may lead to your deployed `traffic_split` being lost; see
377+
the `deployModel` [example](https://cloud.google.com/vertex-ai/docs/general/deployment#deploy_a_model_to_an_endpoint) and
378+
[documentation](https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.endpoints/deployModel) for details.
379+
state_func: 'func(v interface{}) string { s, _ := structure.NormalizeJsonString(v); return s }'
380+
custom_flatten: 'templates/terraform/custom_flatten/json_schema.tmpl'
381+
custom_expand: 'templates/terraform/custom_expand/json_schema.tmpl'
382+
validation:
383+
function: 'validation.StringIsJSON'
361384
- name: 'etag'
362385
type: String
363386
description:
@@ -410,8 +433,38 @@ properties:
410433
enable_private_service_connect, can be set.
411434
[Format](https://cloud.google.com/compute/docs/reference/rest/v1/networks/insert):
412435
`projects/{project}/global/networks/{network}`. Where `{project}` is a
413-
project number, as in `12345`, and `{network}` is network name.'
436+
project number, as in `12345`, and `{network}` is network name.
437+
Only one of the fields, `network` or `privateServiceConnectConfig`, can be set.'
414438
immutable: true
439+
conflicts:
440+
- 'privateServiceConnectConfig'
441+
- name: 'privateServiceConnectConfig'
442+
type: NestedObject
443+
description:
444+
'Configuration for private service connect.
445+
`network` and `privateServiceConnectConfig` are mutually exclusive.'
446+
conflicts:
447+
- 'network'
448+
- 'dedicatedEndpointEnabled'
449+
properties:
450+
- name: 'enablePrivateServiceConnect'
451+
type: Boolean
452+
description:
453+
'Required. If true, expose the IndexEndpoint via private service connect.'
454+
required: true
455+
immutable: true
456+
- name: 'projectAllowlist'
457+
description:
458+
'A list of Projects from which the forwarding rule will target the service attachment.'
459+
type: Array
460+
item_type:
461+
type: String
462+
description:
463+
'A list of Projects from which the forwarding rule will target the service attachment.'
464+
- name: 'enableSecurePrivateServiceConnect'
465+
type: Boolean
466+
description:
467+
'If set to true, enable secure private service connect with IAM authorization. Otherwise, private service connect will be done without authorization. Note latency will be slightly increased if authorization is enabled.'
415468
- name: 'modelDeploymentMonitoringJob'
416469
type: String
417470
description:
@@ -420,3 +473,39 @@ properties:
420473
CreateModelDeploymentMonitoringJob. Format:
421474
`projects/{project}/locations/{location}/modelDeploymentMonitoringJobs/{model_deployment_monitoring_job}`'
422475
output: true
476+
- name: 'predictRequestResponseLoggingConfig'
477+
type: NestedObject
478+
description:
479+
'Configures the request-response logging for online prediction.'
480+
properties:
481+
- name: 'enabled'
482+
type: Boolean
483+
description:
484+
'If logging is enabled or not.'
485+
- name: 'samplingRate'
486+
type: Double
487+
description:
488+
'Percentage of requests to be logged, expressed as a fraction in range(0,1]'
489+
- name: 'bigqueryDestination'
490+
type: NestedObject
491+
description:
492+
'BigQuery table for logging. If only given a project, a new dataset will be created with name `logging_<endpoint-display-name>_<endpoint-id>` where will be made BigQuery-dataset-name compatible (e.g. most special characters will become underscores). If no table name is given, a new table will be created with name `request_response_logging`'
493+
properties:
494+
- name: 'outputUri'
495+
type: String
496+
description:
497+
'BigQuery URI to a project or table, up to 2000 characters long.
498+
When only the project is specified, the Dataset and Table is created. When the full table reference is specified, the Dataset must exist and table must not exist.
499+
Accepted forms:
500+
- BigQuery path. For example: `bq://projectId` or `bq://projectId.bqDatasetId` or `bq://projectId.bqDatasetId.bqTableId`.'
501+
- name: 'dedicatedEndpointEnabled'
502+
type: Boolean
503+
description: |
504+
If true, the endpoint will be exposed through a dedicated DNS [Endpoint.dedicated_endpoint_dns]. Your request to the dedicated DNS will be isolated from other users' traffic and will have better performance and reliability. Note: Once you enabled dedicated endpoint, you won't be able to send request to the shared DNS {region}-aiplatform.googleapis.com. The limitation will be removed soon.
505+
conflicts:
506+
- 'privateServiceConnectConfig'
507+
- name: 'dedicatedEndpointDns'
508+
type: String
509+
description:
510+
'Output only. DNS of the dedicated endpoint. Will only be populated if dedicatedEndpointEnabled is true. Format: `https://{endpointId}.{region}-{projectNumber}.prediction.vertexai.goog`.'
511+
output: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
resource "google_vertex_ai_endpoint" "{{$.PrimaryResourceId}}" {
2+
name = "endpoint-name%{random_suffix}"
3+
display_name = "sample-endpoint"
4+
description = "A sample vertex endpoint"
5+
location = "us-central1"
6+
region = "us-central1"
7+
labels = {
8+
label-one = "value-one"
9+
}
10+
dedicated_endpoint_enabled = true
11+
}
12+
13+
data "google_project" "project" {}

mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.tmpl

+19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ resource "google_vertex_ai_endpoint" "{{$.PrimaryResourceId}}" {
1111
encryption_spec {
1212
kms_key_name = "{{index $.Vars "kms_key_name"}}"
1313
}
14+
predict_request_response_logging_config {
15+
bigquery_destination {
16+
output_uri = "bq://${data.google_project.project.project_id}.${google_bigquery_dataset.bq_dataset.dataset_id}.request_response_logging"
17+
}
18+
enabled = true
19+
sampling_rate = 0.1
20+
}
21+
traffic_split = jsonencode({
22+
"12345" = 100
23+
})
24+
1425
depends_on = [
1526
google_service_networking_connection.vertex_vpc_connection
1627
]
@@ -40,4 +51,12 @@ resource "google_kms_crypto_key_iam_member" "crypto_key" {
4051
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-aiplatform.iam.gserviceaccount.com"
4152
}
4253

54+
resource "google_bigquery_dataset" "bq_dataset" {
55+
dataset_id = "{{index $.Vars "dataset_id"}}"
56+
friendly_name = "logging dataset"
57+
description = "This is a dataset that requests are logged to"
58+
location = "US"
59+
delete_contents_on_destroy = true
60+
}
61+
4362
data "google_project" "project" {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
resource "google_vertex_ai_endpoint" "{{$.PrimaryResourceId}}" {
2+
name = "endpoint-name%{random_suffix}"
3+
display_name = "sample-endpoint"
4+
description = "A sample vertex endpoint"
5+
location = "us-central1"
6+
region = "us-central1"
7+
labels = {
8+
label-one = "value-one"
9+
}
10+
private_service_connect_config {
11+
enable_private_service_connect = true
12+
project_allowlist = [
13+
"${data.google_project.project.project_id}"
14+
]
15+
enable_secure_private_service_connect = false
16+
}
17+
}
18+
19+
data "google_project" "project" {}

mmv1/third_party/terraform/services/vertexai/iam_vertex_endpoint_test.go.tmpl

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func TestAccVertexAIEndpointIamPolicy(t *testing.T) {
9797
ImportStateVerify: true,
9898
},
9999
{
100-
Config: testAccVertexAIEndpointIamPolicy_emptyBinding(context),
100+
Config: testAccVertexAIEndpointIamPolicy_emptyBindingManual(context),
101101
},
102102
{
103103
ResourceName: "google_vertex_ai_endpoint_iam_policy.foo",
@@ -218,7 +218,7 @@ endpoint = google_vertex_ai_endpoint.endpoint.name
218218
`, context)
219219
}
220220

221-
func testAccVertexAIEndpointIamPolicy_emptyBinding(context map[string]interface{}) string {
221+
func testAccVertexAIEndpointIamPolicy_emptyBindingManual(context map[string]interface{}) string {
222222
return acctest.Nprintf(`
223223
resource "google_vertex_ai_endpoint" "endpoint" {
224224
name = "tf-test-endpoint-name%{random_suffix}"

mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go

+15-43
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ package vertexai_test
22

33
import (
44
"fmt"
5-
"strings"
65
"testing"
76

87
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
9-
"github.com/hashicorp/terraform-plugin-testing/terraform"
108
"github.com/hashicorp/terraform-provider-google/google/acctest"
11-
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
12-
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
139
)
1410

1511
func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) {
@@ -64,6 +60,13 @@ resource "google_vertex_ai_endpoint" "endpoint" {
6460
encryption_spec {
6561
kms_key_name = "%{kms_key_name}"
6662
}
63+
predict_request_response_logging_config {
64+
bigquery_destination {
65+
output_uri = "bq://${data.google_project.project.project_id}.${google_bigquery_dataset.bq_dataset.dataset_id}.request_response_logging"
66+
}
67+
enabled = true
68+
sampling_rate = 0.1
69+
}
6770
6871
depends_on = [google_kms_crypto_key_iam_member.crypto_key]
6972
}
@@ -78,6 +81,14 @@ resource "google_kms_crypto_key_iam_member" "crypto_key" {
7881
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-aiplatform.iam.gserviceaccount.com"
7982
}
8083
84+
resource "google_bigquery_dataset" "bq_dataset" {
85+
dataset_id = "some_dataset%{endpoint_name}"
86+
friendly_name = "logging dataset"
87+
description = "This is a dataset that requests are logged to"
88+
location = "US"
89+
delete_contents_on_destroy = true
90+
}
91+
8192
data "google_project" "project" {}
8293
`, context)
8394
}
@@ -114,42 +125,3 @@ resource "google_kms_crypto_key_iam_member" "crypto_key" {
114125
data "google_project" "project" {}
115126
`, context)
116127
}
117-
118-
func testAccCheckVertexAIEndpointDestroyProducer(t *testing.T) func(s *terraform.State) error {
119-
return func(s *terraform.State) error {
120-
for name, rs := range s.RootModule().Resources {
121-
if rs.Type != "google_vertex_ai_endpoint" {
122-
continue
123-
}
124-
if strings.HasPrefix(name, "data.") {
125-
continue
126-
}
127-
128-
config := acctest.GoogleProviderConfig(t)
129-
130-
url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{VertexAIBasePath}}projects/{{project}}/locations/{{location}}/endpoints/{{name}}")
131-
if err != nil {
132-
return err
133-
}
134-
135-
billingProject := ""
136-
137-
if config.BillingProject != "" {
138-
billingProject = config.BillingProject
139-
}
140-
141-
_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
142-
Config: config,
143-
Method: "GET",
144-
Project: billingProject,
145-
RawURL: url,
146-
UserAgent: config.UserAgent,
147-
})
148-
if err == nil {
149-
return fmt.Errorf("VertexAIEndpoint still exists at %s", url)
150-
}
151-
}
152-
153-
return nil
154-
}
155-
}

0 commit comments

Comments
 (0)