From 6b8300c17dcff5122208fed6414503f12e30c9c5 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Tue, 8 Sep 2026 20:12:36 +0000 Subject: [PATCH] Add Vertex AI RagCorpus resource (#18889) [upstream:d3fb38b1ccca391c45fd2cbc00a67e4e2cf5d72b] Signed-off-by: Modular Magician --- .changelog/18889.txt | 3 + .../vertexai/list_vertex_ai_rag_corpus.go | 184 +++ ...ist_vertex_ai_rag_corpus_generated_test.go | 108 ++ .../vertexai/resource_vertex_ai_rag_corpus.go | 1174 +++++++++++++++++ ...e_vertex_ai_rag_corpus_generated_meta.yaml | 27 + ...rce_vertex_ai_rag_corpus_generated_test.go | 227 ++++ .../resource_vertex_ai_rag_corpus_sweeper.go | 223 ++++ .../google_vertex_ai_rag_corpus.html.markdown | 52 + .../docs/r/vertex_ai_rag_corpus.html.markdown | 296 +++++ 9 files changed, 2294 insertions(+) create mode 100644 .changelog/18889.txt create mode 100644 google-beta/services/vertexai/list_vertex_ai_rag_corpus.go create mode 100644 google-beta/services/vertexai/list_vertex_ai_rag_corpus_generated_test.go create mode 100644 google-beta/services/vertexai/resource_vertex_ai_rag_corpus.go create mode 100644 google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_meta.yaml create mode 100644 google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_test.go create mode 100644 google-beta/services/vertexai/resource_vertex_ai_rag_corpus_sweeper.go create mode 100644 website/docs/list-resources/google_vertex_ai_rag_corpus.html.markdown create mode 100644 website/docs/r/vertex_ai_rag_corpus.html.markdown diff --git a/.changelog/18889.txt b/.changelog/18889.txt new file mode 100644 index 0000000000..2cae3650e1 --- /dev/null +++ b/.changelog/18889.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_vertex_ai_rag_corpus` +``` \ No newline at end of file diff --git a/google-beta/services/vertexai/list_vertex_ai_rag_corpus.go b/google-beta/services/vertexai/list_vertex_ai_rag_corpus.go new file mode 100644 index 0000000000..976c3f2505 --- /dev/null +++ b/google-beta/services/vertexai/list_vertex_ai_rag_corpus.go @@ -0,0 +1,184 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/RagCorpus.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/list_resource.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package vertexai + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/list" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/registry" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func init() { + registry.FrameworkListResource{ + Name: "google_vertex_ai_rag_corpus", + ProductName: "VertexAI", + Func: NewVertexAIRagCorpusListResource, + }.Register() +} + +var _ list.ListResource = &VertexAIRagCorpusListResource{} + +type VertexAIRagCorpusListResource struct { + tpgresource.ListResourceMetadata +} + +func NewVertexAIRagCorpusListResource() list.ListResource { + listR := &VertexAIRagCorpusListResource{} + listR.TypeName = "google_vertex_ai_rag_corpus" + listR.SDKv2Resource = ResourceVertexAIRagCorpus() + listR.ListConfigFields = []tpgresource.ListConfigField{ + {Name: "region", Kind: tpgresource.ListConfigKindString, Optional: false}, + {Name: "project", Kind: tpgresource.ListConfigKindString, Optional: true}, + } + return listR +} + +// VertexAIRagCorpusListModel matches ListResourceMetadata.ListConfigFields (tfsdk names and types). +type VertexAIRagCorpusListModel struct { + Region types.String `tfsdk:"region"` + Project types.String `tfsdk:"project"` +} + +func (listR *VertexAIRagCorpusListResource) List(ctx context.Context, listReq list.ListRequest, stream *list.ListResultsStream) { + var data VertexAIRagCorpusListModel + diags := listReq.Config.Get(ctx, &data) + if diags.HasError() { + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + if listR.Client == nil { + diags = append(diags, diag.NewErrorDiagnostic( + "Provider not configured", + "The Google provider client is not available; ensure the provider is configured (e.g. credentials and default project).", + )) + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + region := listR.GetRegion(data.Region) + project := listR.GetProject(data.Project) + + errStreamClosed := errors.New("stream closed") + stream.Results = func(push func(list.ListResult) bool) { + err := ListVertexAIRagCorpuss( + listR.Client, + region, + project, + func(rd *schema.ResourceData) error { + result := listReq.NewListResult(ctx) + + if err := listR.SetResult(ctx, listReq.IncludeResource, &result, rd, "name"); err != nil { + return err + } + + if !push(result) { + return errStreamClosed + } + return nil + }, + ) + // A closed stream is not an error: return without pushing again. + if err == nil || errors.Is(err, errStreamClosed) { + return + } + diags.AddError("API Error", err.Error()) + result := listReq.NewListResult(ctx) + result.Diagnostics = diags + push(result) + } +} + +func ListVertexAIRagCorpuss(config *transport_tpg.Config, + region string, + project string, + callback func(*schema.ResourceData) error, +) error { + resourceData := ResourceVertexAIRagCorpus().Data(&terraform.InstanceState{}) + if region != "" { + if err := resourceData.Set("region", region); err != nil { + return fmt.Errorf("error setting region on temporary resource data: %w", err) + } + } + if project != "" { + if err := resourceData.Set("project", project); err != nil { + return fmt.Errorf("error setting project on temporary resource data: %w", err) + } + } + + url, err := tpgresource.ReplaceVars(resourceData, config, "{{VertexAIBasePath}}projects/{{project}}/locations/{{region}}/ragCorpora") + if err != nil { + return err + } + billingProject := project + if bp, err := tpgresource.GetBillingProject(resourceData, config); err == nil { + billingProject = bp + } + + userAgent, err := tpgresource.GenerateUserAgentString(resourceData, config.UserAgent) + if err != nil { + return err + } + return transport_tpg.ListPages(transport_tpg.ListPagesOptions{ + Config: config, + TempData: resourceData, + Resource: ResourceVertexAIRagCorpus(), + ListURL: url, + BillingProject: billingProject, + UserAgent: userAgent, + ItemName: "ragCorpora", + Flattener: func(res map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) error { + headers := make(http.Header) + var err error + if v, ok := res["name"]; ok && v != nil { + if err := d.Set("name", v); err != nil { + return fmt.Errorf("error setting name: %w", err) + } + } + if v, ok := res["region"]; ok && v != nil { + if s, ok := v.(string); ok { + v = tpgresource.GetResourceNameFromSelfLink(s) + } + if err := d.Set("region", v); err != nil { + return fmt.Errorf("error setting region: %w", err) + } + } + if err = ResourceVertexAIRagCorpusFlatten(d, config, res, config, project, userAgent, billingProject, url, headers); err != nil { + return err + } + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return fmt.Errorf("error constructing id: %w", err) + } + d.SetId(id) + return nil + }, + Callback: callback, + }) +} diff --git a/google-beta/services/vertexai/list_vertex_ai_rag_corpus_generated_test.go b/google-beta/services/vertexai/list_vertex_ai_rag_corpus_generated_test.go new file mode 100644 index 0000000000..6d5c9306f1 --- /dev/null +++ b/google-beta/services/vertexai/list_vertex_ai_rag_corpus_generated_test.go @@ -0,0 +1,108 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/RagCorpus.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/samples/base_configs/query_test_file.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package vertexai_test + +import ( + "strings" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/querycheck/queryfilter" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + _ "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/resourcemanager" + _ "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/vertexai" +) + +var ( + _ = strings.Trim + _ = envvar.TestEnvVar + _ = time.Now +) + +func TestAccVertexAIRagCorpusListQuery_generated(t *testing.T) { + + t.Parallel() + + randomSuffix := acctest.RandString(t, 10) + context := map[string]interface{}{ + "display_name": "tf-test-rag-corpus" + randomSuffix, + "region": envvar.GetTestRegionFromEnv(), + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": randomSuffix, + } + + var listDisplayName acctest.ListDisplayName + var listScope acctest.ListScopeCapture + acctest.VcrTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVertexAIRagCorpusDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVertexAIRagCorpus_vertexAiRagCorpusBasicExample(context), + Check: resource.ComposeTestCheckFunc( + listDisplayName.Capture( + "google_vertex_ai_rag_corpus.example", + []string{ + "name", + }, + ), + listScope.Capture(map[string]string{ + "region": "google_vertex_ai_rag_corpus.example", + }), + ), + }, + { + Query: true, + Config: testAccVertexAIRagCorpus_vertexAiRagCorpusBasicExampleListQuery(context), + ConfigVariables: listScope.AsConfigVariables(), + QueryResultChecks: []querycheck.QueryResultCheck{ + querycheck.ExpectLengthAtLeast("google_vertex_ai_rag_corpus.list_query", 1), + querycheck.ExpectResourceDisplayName( + "google_vertex_ai_rag_corpus.list_query", + queryfilter.ByDisplayName(listDisplayName.CheckValue()), + listDisplayName.CheckValue(), + ), + }, + }, + }, + }) +} + +func testAccVertexAIRagCorpus_vertexAiRagCorpusBasicExampleListQuery(context map[string]interface{}) string { + return acctest.Nprintf(` +variable "region" { type = string } +list "google_vertex_ai_rag_corpus" "list_query" { + provider = google + limit = 10000 + config { + region = var.region + } +} +`, context) +} diff --git a/google-beta/services/vertexai/resource_vertex_ai_rag_corpus.go b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus.go new file mode 100644 index 0000000000..5befd2432d --- /dev/null +++ b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus.go @@ -0,0 +1,1174 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/RagCorpus.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/resource.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package vertexai + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "log" + "net/http" + "reflect" + "regexp" + "slices" + "sort" + "strconv" + "strings" + "time" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/registry" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" + + "google.golang.org/api/googleapi" +) + +var ( + _ = bytes.Clone + _ = context.WithCancel + _ = base64.NewDecoder + _ = json.Marshal + _ = fmt.Sprintf + _ = log.Print + _ = http.Get + _ = reflect.ValueOf + _ = regexp.Match + _ = slices.Min([]int{1}) + _ = sort.IntSlice{} + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = errwrap.Wrap + _ = cty.BoolVal + _ = diag.Diagnostic{} + _ = customdiff.All + _ = id.UniqueId + _ = logging.LogLevel + _ = retry.Retry + _ = schema.Noop + _ = validation.All + _ = structure.ExpandJsonFromString + _ = terraform.State{} + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = verify.ValidateEnum + _ = googleapi.Error{} +) + +func init() { + registry.Schema{ + Name: "google_vertex_ai_rag_corpus", + ProductName: "vertexai", + Type: registry.SchemaTypeResource, + Schema: ResourceVertexAIRagCorpus(), + }.Register() +} + +func ResourceVertexAIRagCorpus() *schema.Resource { + return &schema.Resource{ + Create: resourceVertexAIRagCorpusCreate, + Read: resourceVertexAIRagCorpusRead, + Update: resourceVertexAIRagCorpusUpdate, + Delete: resourceVertexAIRagCorpusDelete, + + Importer: &schema.ResourceImporter{ + State: resourceVertexAIRagCorpusImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderDeletionPolicy("DELETE"), + ), + + Identity: &schema.ResourceIdentity{ + Version: 1, + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + RequiredForImport: true, + }, + "region": { + Type: schema.TypeString, + RequiredForImport: true, + }, + "project": { + Type: schema.TypeString, + OptionalForImport: true, + }, + } + }, + }, + ResourceBehavior: schema.ResourceBehavior{ + MutableIdentity: true, + }, + + Schema: map[string]*schema.Schema{ + "display_name": { + Type: schema.TypeString, + Required: true, + Description: `Required. The display name of the RagCorpus. The name can be up to 128 +characters long and can consist of any UTF-8 characters.`, + }, + "region": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The region of the RagCorpus. eg europe-west4`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `Optional. The description of the RagCorpus.`, + }, + "encryption_spec": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Optional. Immutable. The CMEK key name used to encrypt at-rest data +related to this corpus. Only applicable to RagManagedDb option for Vector +DB. This field can only be set at corpus creation time, and cannot be +updated or deleted.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kms_key_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Required. The Cloud KMS resource identifier of the customer managed +encryption key used to protect the resource. Has the form: +projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key. +The key needs to be in the same region as where the resource is +created.`, + }, + }, + }, + }, + "vector_db_config": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Optional. Immutable. The config for the RAG-managed Vector DB.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rag_embedding_model_config": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Optional. Immutable. The embedding model config of the Vector DB.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vertex_prediction_endpoint": { + Type: schema.TypeList, + Optional: true, + Description: `The Vertex AI Prediction Endpoint used for dense vector search.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "endpoint": { + Type: schema.TypeString, + Required: true, + Description: `Required. The endpoint resource name. Format: +projects/{project}/locations/{location}/publishers/{publisher}/models/{model} +or projects/{project}/locations/{location}/endpoints/{endpoint}.`, + }, + "model": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. The resource name of the model that is deployed on the endpoint.`, + }, + "model_version_id": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. Version ID of the model that is deployed on the endpoint.`, + }, + }, + }, + }, + }, + }, + }, + "rag_managed_db": { + Type: schema.TypeList, + Optional: true, + Description: `The config for the default RAG-managed Vector DB.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ann": { + Type: schema.TypeList, + Optional: true, + Description: `Performs an ANN search on RagCorpus.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "leaf_count": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Number of leaf nodes in the tree-based structure. Default value is 500.`, + }, + "tree_depth": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `The depth of the tree-based structure. Only depth values of 2 and 3 are supported. Default value is 2.`, + }, + }, + }, + ExactlyOneOf: []string{"vector_db_config.0.rag_managed_db.0.ann", "vector_db_config.0.rag_managed_db.0.knn"}, + }, + "knn": { + Type: schema.TypeList, + Optional: true, + Description: `Performs a KNN search on RagCorpus. This is the default choice if not specified.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{}, + }, + ExactlyOneOf: []string{"vector_db_config.0.rag_managed_db.0.ann", "vector_db_config.0.rag_managed_db.0.knn"}, + }, + }, + }, + }, + }, + }, + }, + "corpus_status": { + Type: schema.TypeList, + Computed: true, + Description: `Output only. RagCorpus state.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "error_status": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. Only populated when the state is ERROR.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. RagCorpus life state.`, + }, + }, + }, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. Timestamp when this RagCorpus was created.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The generated name of the RagCorpus, in the format +projects/{project}/locations/{location}/ragCorpora/{rag_corpus}.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. Timestamp when this RagCorpus was last updated.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "deletion_policy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Whether Terraform will be prevented from destroying the instance. Defaults to "DELETE". +When a 'terraform destroy' or 'terraform apply' would delete the instance, +the command will fail if this field is set to "PREVENT" in Terraform state. +When set to "ABANDON", the command will remove the resource from Terraform +management without updating or deleting the resource in the API. +When set to "DELETE", deleting the resource is allowed. +`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceVertexAIRagCorpusCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + displayNameProp, err := expandVertexAIRagCorpusDisplayName(d.Get("display_name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("display_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + descriptionProp, err := expandVertexAIRagCorpusDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + vectorDbConfigProp, err := expandVertexAIRagCorpusVectorDbConfig(d.Get("vector_db_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("vector_db_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(vectorDbConfigProp)) && (ok || !reflect.DeepEqual(v, vectorDbConfigProp)) { + obj["vectorDbConfig"] = vectorDbConfigProp + } + encryptionSpecProp, err := expandVertexAIRagCorpusEncryptionSpec(d.Get("encryption_spec"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("encryption_spec"); !tpgresource.IsEmptyValue(reflect.ValueOf(encryptionSpecProp)) && (ok || !reflect.DeepEqual(v, encryptionSpecProp)) { + obj["encryptionSpec"] = encryptionSpecProp + } + + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/locations/{{region}}/ragCorpora") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new RagCorpus: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RagCorpus: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating RagCorpus: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + // Use the resource in the operation response to populate + // identity fields and d.Id() before read + var opRes map[string]interface{} + err = VertexAIOperationWaitTimeWithResponse( + config, res, &opRes, project, "Creating RagCorpus", userAgent, + d.Timeout(schema.TimeoutCreate)) + if err != nil { + // The resource didn't actually create + d.SetId("") + + return fmt.Errorf("Error waiting to create RagCorpus: %s", err) + } + + if err := d.Set("name", flattenVertexAIRagCorpusName(opRes["name"], d, config)); err != nil { + return err + } + + // This may have caused the ID to update - update it if so. + id, err = tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating RagCorpus %q: %#v", d.Id(), res) + + identity, err := d.Identity() + if err == nil && identity != nil { + if nameValue, ok := d.GetOk("name"); ok && nameValue.(string) != "" { + if err = identity.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("Error setting name: %s", err) + } + } + if regionValue, ok := d.GetOk("region"); ok && regionValue.(string) != "" { + if err = identity.Set("region", regionValue.(string)); err != nil { + return fmt.Errorf("Error setting region: %s", err) + } + } + if projectValue, ok := d.GetOk("project"); ok && projectValue.(string) != "" { + if err = identity.Set("project", projectValue.(string)); err != nil { + return fmt.Errorf("Error setting project: %s", err) + } + } + } else { + log.Printf("[DEBUG] (Create) identity not set: %s", err) + } + + return resourceVertexAIRagCorpusRead(d, meta) +} + +func resourceVertexAIRagCorpusRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RagCorpus: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("VertexAIRagCorpus %q", d.Id())) + } + + log.Printf("[DEBUG] Finished reading VertexAIRagCorpus %q: %#v", d.Id(), res) + + // Explicitly set virtual fields to default values if unset + if _, ok := d.GetOkExists("deletion_policy"); !ok { + //prioritize config's value if present + if config.DeletionPolicy != "" { + if err := d.Set("deletion_policy", config.DeletionPolicy); err != nil { + return fmt.Errorf("Error setting deletion_policy: %s", err) + } + } else { + if err := d.Set("deletion_policy", "DELETE"); err != nil { + return fmt.Errorf("Error setting deletion_policy: %s", err) + } + } + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + + err = ResourceVertexAIRagCorpusFlatten(d, meta, res, config, project, userAgent, billingProject, url, headers) + if err != nil { + return err + } + + identity, err := d.Identity() + if err == nil && identity != nil { + if v, ok := identity.GetOk("name"); !ok && v == "" { + err = identity.Set("name", d.Get("name").(string)) + if err != nil { + return fmt.Errorf("Error setting name: %s", err) + } + } + if v, ok := identity.GetOk("region"); !ok && v == "" { + err = identity.Set("region", d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error setting region: %s", err) + } + } + if v, ok := identity.GetOk("project"); !ok && v == "" { + err = identity.Set("project", d.Get("project").(string)) + if err != nil { + return fmt.Errorf("Error setting project: %s", err) + } + } + } else { + log.Printf("[DEBUG] (Read) identity not set: %s", err) + } + + return nil +} + +func resourceVertexAIRagCorpusUpdate(d *schema.ResourceData, meta interface{}) error { + clientSideFields := map[string]bool{"deletion_policy": true} + clientSideOnly := true + for field := range ResourceVertexAIRagCorpus().Schema { + if d.HasChange(field) && !clientSideFields[field] { + clientSideOnly = false + break + } + } + if clientSideOnly { + log.Print("[DEBUG] Only client-side changes detected. Cancelling update operation.") + return resourceVertexAIRagCorpusRead(d, meta) + } + + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + identity, err := d.Identity() + if err == nil && identity != nil { + if nameValue, ok := d.GetOk("name"); ok && nameValue.(string) != "" { + if err = identity.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("Error setting name: %s", err) + } + } + if regionValue, ok := d.GetOk("region"); ok && regionValue.(string) != "" { + if err = identity.Set("region", regionValue.(string)); err != nil { + return fmt.Errorf("Error setting region: %s", err) + } + } + if projectValue, ok := d.GetOk("project"); ok && projectValue.(string) != "" { + if err = identity.Set("project", projectValue.(string)); err != nil { + return fmt.Errorf("Error setting project: %s", err) + } + } + } else { + log.Printf("[DEBUG] (Update) identity not set: %s", err) + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RagCorpus: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + displayNameProp, err := expandVertexAIRagCorpusDisplayName(d.Get("display_name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("display_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + descriptionProp, err := expandVertexAIRagCorpusDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating RagCorpus %q: %#v", d.Id(), obj) + headers := make(http.Header) + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating RagCorpus %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating RagCorpus %q: %#v", d.Id(), res) + } + + err = VertexAIOperationWaitTime( + config, res, project, "Updating RagCorpus", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + + return resourceVertexAIRagCorpusRead(d, meta) +} + +func resourceVertexAIRagCorpusDelete(d *schema.ResourceData, meta interface{}) error { + if d.Get("deletion_policy").(string) == "PREVENT" { + return fmt.Errorf("cannot destroy VertexAIRagCorpus without setting deletion_policy=\"DELETE\" and running `terraform apply`") + } + if d.Get("deletion_policy").(string) == "ABANDON" { + log.Printf("[DEBUG] deletion_policy set to \"ABANDON\", removing RagCorpus %q from Terraform state without deletion", d.Id()) + return nil + } + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RagCorpus: %s", err) + } + billingProject = project + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting RagCorpus %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "RagCorpus") + } + + err = VertexAIOperationWaitTime( + config, res, project, "Deleting RagCorpus", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting RagCorpus %q: %#v", d.Id(), res) + return nil +} + +func resourceVertexAIRagCorpusImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/locations/(?P[^/]+)/ragCorpora/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenVertexAIRagCorpusName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return tpgresource.GetResourceNameFromSelfLink(v.(string)) +} + +func flattenVertexAIRagCorpusDisplayName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusCorpusStatus(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["state"] = + flattenVertexAIRagCorpusCorpusStatusState(original["state"], d, config) + transformed["error_status"] = + flattenVertexAIRagCorpusCorpusStatusErrorStatus(original["errorStatus"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusCorpusStatusState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusCorpusStatusErrorStatus(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusVectorDbConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["rag_managed_db"] = + flattenVertexAIRagCorpusVectorDbConfigRagManagedDb(original["ragManagedDb"], d, config) + transformed["rag_embedding_model_config"] = + flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfig(original["ragEmbeddingModelConfig"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusVectorDbConfigRagManagedDb(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["knn"] = + flattenVertexAIRagCorpusVectorDbConfigRagManagedDbKnn(original["knn"], d, config) + transformed["ann"] = + flattenVertexAIRagCorpusVectorDbConfigRagManagedDbAnn(original["ann"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusVectorDbConfigRagManagedDbKnn(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + transformed := make(map[string]interface{}) + return []interface{}{transformed} +} + +func flattenVertexAIRagCorpusVectorDbConfigRagManagedDbAnn(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["tree_depth"] = + flattenVertexAIRagCorpusVectorDbConfigRagManagedDbAnnTreeDepth(original["treeDepth"], d, config) + transformed["leaf_count"] = + flattenVertexAIRagCorpusVectorDbConfigRagManagedDbAnnLeafCount(original["leafCount"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusVectorDbConfigRagManagedDbAnnTreeDepth(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenVertexAIRagCorpusVectorDbConfigRagManagedDbAnnLeafCount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["vertex_prediction_endpoint"] = + flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpoint(original["vertexPredictionEndpoint"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpoint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["endpoint"] = + flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointEndpoint(original["endpoint"], d, config) + transformed["model"] = + flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModel(original["model"], d, config) + transformed["model_version_id"] = + flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModelVersionId(original["modelVersionId"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointEndpoint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModelVersionId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVertexAIRagCorpusEncryptionSpec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["kms_key_name"] = + flattenVertexAIRagCorpusEncryptionSpecKmsKeyName(original["kmsKeyName"], d, config) + return []interface{}{transformed} +} +func flattenVertexAIRagCorpusEncryptionSpecKmsKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandVertexAIRagCorpusDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusVectorDbConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRagManagedDb, err := expandVertexAIRagCorpusVectorDbConfigRagManagedDb(original["rag_managed_db"], d, config) + if err != nil { + return nil, err + } else { + transformed["ragManagedDb"] = transformedRagManagedDb + } + + transformedRagEmbeddingModelConfig, err := expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfig(original["rag_embedding_model_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRagEmbeddingModelConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ragEmbeddingModelConfig"] = transformedRagEmbeddingModelConfig + } + + return transformed, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagManagedDb(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + + if l[0] == nil { + transformed := make(map[string]interface{}) + return transformed, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedKnn, err := expandVertexAIRagCorpusVectorDbConfigRagManagedDbKnn(original["knn"], d, config) + if err != nil { + return nil, err + } else { + transformed["knn"] = transformedKnn + } + + transformedAnn, err := expandVertexAIRagCorpusVectorDbConfigRagManagedDbAnn(original["ann"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAnn); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["ann"] = transformedAnn + } + + return transformed, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagManagedDbKnn(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + + if l[0] == nil { + transformed := make(map[string]interface{}) + return transformed, nil + } + transformed := make(map[string]interface{}) + + return transformed, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagManagedDbAnn(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTreeDepth, err := expandVertexAIRagCorpusVectorDbConfigRagManagedDbAnnTreeDepth(original["tree_depth"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTreeDepth); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["treeDepth"] = transformedTreeDepth + } + + transformedLeafCount, err := expandVertexAIRagCorpusVectorDbConfigRagManagedDbAnnLeafCount(original["leaf_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLeafCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["leafCount"] = transformedLeafCount + } + + return transformed, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagManagedDbAnnTreeDepth(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagManagedDbAnnLeafCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedVertexPredictionEndpoint, err := expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpoint(original["vertex_prediction_endpoint"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVertexPredictionEndpoint); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vertexPredictionEndpoint"] = transformedVertexPredictionEndpoint + } + + return transformed, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpoint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEndpoint, err := expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointEndpoint(original["endpoint"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEndpoint); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["endpoint"] = transformedEndpoint + } + + transformedModel, err := expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModel(original["model"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedModel); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["model"] = transformedModel + } + + transformedModelVersionId, err := expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModelVersionId(original["model_version_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedModelVersionId); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["modelVersionId"] = transformedModelVersionId + } + + return transformed, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointEndpoint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusVectorDbConfigRagEmbeddingModelConfigVertexPredictionEndpointModelVersionId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIRagCorpusEncryptionSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedKmsKeyName, err := expandVertexAIRagCorpusEncryptionSpecKmsKeyName(original["kms_key_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["kmsKeyName"] = transformedKmsKeyName + } + + return transformed, nil +} + +func expandVertexAIRagCorpusEncryptionSpecKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func ResourceVertexAIRagCorpusFlatten(d *schema.ResourceData, meta interface{}, res map[string]interface{}, config *transport_tpg.Config, project string, userAgent string, billingProject string, url string, headers http.Header) error { + var err error + + if err = d.Set("name", flattenVertexAIRagCorpusName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("display_name", flattenVertexAIRagCorpusDisplayName(res["displayName"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("description", flattenVertexAIRagCorpusDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("create_time", flattenVertexAIRagCorpusCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("update_time", flattenVertexAIRagCorpusUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("corpus_status", flattenVertexAIRagCorpusCorpusStatus(res["corpusStatus"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("vector_db_config", flattenVertexAIRagCorpusVectorDbConfig(res["vectorDbConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + if err = d.Set("encryption_spec", flattenVertexAIRagCorpusEncryptionSpec(res["encryptionSpec"], d, config)); err != nil { + return fmt.Errorf("Error reading RagCorpus: %s", err) + } + + return nil +} diff --git a/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_meta.yaml b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_meta.yaml new file mode 100644 index 0000000000..d69a91254a --- /dev/null +++ b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_meta.yaml @@ -0,0 +1,27 @@ +# Copyright IBM Corp. 2014, 2026 +# SPDX-License-Identifier: MPL-2.0 +resource: google_vertex_ai_rag_corpus +generation_type: mmv1 +source_file: products/vertexai/RagCorpus.yaml +api_service_name: aiplatform.googleapis.com +api_version: v1beta1 +api_resource_type_kind: RagCorpus +fields: + - api_field: corpusStatus.errorStatus + - api_field: corpusStatus.state + - api_field: createTime + - api_field: description + - api_field: displayName + - api_field: encryptionSpec.kmsKeyName + - api_field: name + - field: region + provider_only: true + - api_field: updateTime + - api_field: vectorDbConfig.ragEmbeddingModelConfig.vertexPredictionEndpoint.endpoint + - api_field: vectorDbConfig.ragEmbeddingModelConfig.vertexPredictionEndpoint.model + - api_field: vectorDbConfig.ragEmbeddingModelConfig.vertexPredictionEndpoint.modelVersionId + - api_field: vectorDbConfig.ragManagedDb.ann.leafCount + - api_field: vectorDbConfig.ragManagedDb.ann.treeDepth + - api_field: vectorDbConfig.ragManagedDb.knn + - field: deletion_policy + provider_only: true diff --git a/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_test.go b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_test.go new file mode 100644 index 0000000000..3a46a47072 --- /dev/null +++ b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_generated_test.go @@ -0,0 +1,227 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package vertexai_test + +import ( + "fmt" + "log" + "regexp" + "strconv" + "strings" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/kms" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/resourcemanager" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/vertexai" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + + "google.golang.org/api/googleapi" +) + +var ( + _ = fmt.Sprintf + _ = log.Print + _ = regexp.MatchString + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = resource.TestMain + _ = terraform.NewState + _ = envvar.TestEnvVar + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = googleapi.Error{} + _ = vertexai.Product +) + +func TestAccVertexAIRagCorpus_vertexAiRagCorpusBasicExample(t *testing.T) { + t.Parallel() + + randomSuffix := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "display_name": "tf-test-rag-corpus" + randomSuffix, + "random_suffix": randomSuffix, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVertexAIRagCorpusDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVertexAIRagCorpus_vertexAiRagCorpusBasicExample(context), + }, + { + ResourceName: "google_vertex_ai_rag_corpus.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"region"}, + }, + { + ResourceName: "google_vertex_ai_rag_corpus.example", + RefreshState: true, + ExpectNonEmptyPlan: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + }, + }, + }) +} + +func testAccVertexAIRagCorpus_vertexAiRagCorpusBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_vertex_ai_rag_corpus" "example" { + display_name = "%{display_name}" + description = "A basic RAG corpus" + region = "europe-west4" + + vector_db_config { + rag_managed_db { + knn {} + } + + rag_embedding_model_config { + vertex_prediction_endpoint { + endpoint = "projects/${data.google_project.project.number}/locations/europe-west4/publishers/google/models/text-embedding-005" + } + } + } +} + +data "google_project" "project" { +} +`, context) +} + +func TestAccVertexAIRagCorpus_vertexAiRagCorpusFullExample(t *testing.T) { + t.Parallel() + resourcemanager.BootstrapIamMembers(t, []resourcemanager.IamMember{ + { + Member: "serviceAccount:service-{project_number}@gcp-sa-vertex-rag.iam.gserviceaccount.com", + Role: "roles/cloudkms.cryptoKeyEncrypterDecrypter", + }, + }) + + randomSuffix := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "display_name": "tf-test-rag-corpus-full" + randomSuffix, + "kms_key_name": kms.BootstrapKMSKeyInLocation(t, "europe-west4").CryptoKey.Name, + "random_suffix": randomSuffix, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVertexAIRagCorpusDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVertexAIRagCorpus_vertexAiRagCorpusFullExample(context), + }, + { + ResourceName: "google_vertex_ai_rag_corpus.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"region"}, + }, + { + ResourceName: "google_vertex_ai_rag_corpus.example", + RefreshState: true, + ExpectNonEmptyPlan: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + }, + }, + }) +} + +func testAccVertexAIRagCorpus_vertexAiRagCorpusFullExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_vertex_ai_rag_corpus" "example" { + display_name = "%{display_name}" + description = "A RAG corpus with a customer-managed encryption key" + region = "europe-west4" + + vector_db_config { + rag_managed_db { + ann { + tree_depth = 2 + leaf_count = 500 + } + } + + rag_embedding_model_config { + vertex_prediction_endpoint { + endpoint = "projects/${data.google_project.project.number}/locations/europe-west4/publishers/google/models/text-embedding-005" + } + } + } + + encryption_spec { + kms_key_name = "%{kms_key_name}" + } +} + +data "google_project" "project" { +} +`, context) +} + +func testAccCheckVertexAIRagCorpusDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_vertex_ai_rag_corpus" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + url, err := tpgresource.ReplaceVarsForTest(config, rs, transport_tpg.BaseUrl(vertexai.Product, config)+"projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("VertexAIRagCorpus still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_sweeper.go b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_sweeper.go new file mode 100644 index 0000000000..6e0d5ef42b --- /dev/null +++ b/google-beta/services/vertexai/resource_vertex_ai_rag_corpus_sweeper.go @@ -0,0 +1,223 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/RagCorpus.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/sweeper_file.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package vertexai + +import ( + "context" + "fmt" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/sweeper" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func init() { + // Initialize base sweeper object + s := &sweeper.Sweeper{ + Name: "google_vertex_ai_rag_corpus", + ListAndAction: listAndActionVertexAIRagCorpus, + DeleteFunction: testSweepVertexAIRagCorpus, + } + + // Register the sweeper + sweeper.AddTestSweepers(s) +} + +func testSweepVertexAIRagCorpus(_ string) error { + return listAndActionVertexAIRagCorpus(deleteResourceVertexAIRagCorpus) +} + +func listAndActionVertexAIRagCorpus(action sweeper.ResourceAction) error { + var lastError error + resourceName := "VertexAIRagCorpus" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + // Prepare configurations to iterate over + var configs []*tpgresource.ResourceDataMock + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + // Default single config + intermediateValues := []map[string]string{ + { + "region": "us-central1", + }, + } + + // Create configs from intermediate values + for _, values := range intermediateValues { + mockConfig := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "billing_account": billingId, + }, + } + + // Apply all provided values + for key, value := range values { + mockConfig.FieldsInSchema[key] = value + } + + // Set fallback values for common fields + region, hasRegion := mockConfig.FieldsInSchema["region"].(string) + if !hasRegion { + region = "us-central1" + mockConfig.FieldsInSchema["region"] = region + } + + if _, hasLocation := mockConfig.FieldsInSchema["location"]; !hasLocation { + mockConfig.FieldsInSchema["location"] = region + } + + if _, hasZone := mockConfig.FieldsInSchema["zone"]; !hasZone { + mockConfig.FieldsInSchema["zone"] = region + "-a" + } + + configs = append(configs, mockConfig) + } + + // Process all configurations (either from parent resources or direct substitutions) + for _, mockConfig := range configs { + // Get region from config + region := sweeper.GetFieldOrDefault(mockConfig, "region", "us-central1") + + // Create shared config for this region + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + lastError = err + continue + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + lastError = err + continue + } + + // Prepare list URL + listTemplate := strings.Split("https://{{region}}-aiplatform.googleapis.com/v1beta1/projects/{{project}}/locations/{{region}}/ragCorpora", "?")[0] + listUrl, err := tpgresource.ReplaceVars(mockConfig, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + lastError = err + continue + } + + // Log additional info for parent-based resources + log.Printf("[INFO][SWEEPER_LOG] Listing %s resources at %s", resourceName, listUrl) + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + lastError = err + continue + } + + // First try the expected resource key + resourceList, ok := res["ragCorpora"] + if ok { + log.Printf("[INFO][SWEEPER_LOG] Found resources under expected key 'ragCorpora'") + } else { + // Next, try the common "items" pattern + resourceList, ok = res["items"] + if ok { + log.Printf("[INFO][SWEEPER_LOG] Found resources under standard 'items' key") + } else { + log.Printf("[INFO][SWEEPER_LOG] no resources found") + continue + } + } + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj, ok := ri.(map[string]interface{}) + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Item was not a map: %T", ri) + continue + } + + if err := action(config, mockConfig, obj); err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in action: %s", err) + lastError = err + } else { + nonPrefixCount++ + } + } + } + + return lastError +} + +func deleteResourceVertexAIRagCorpus(config *transport_tpg.Config, d *tpgresource.ResourceDataMock, obj map[string]interface{}) error { + var deletionerror error + resourceName := "VertexAIRagCorpus" + var name string + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return fmt.Errorf("%s resource name was nil", resourceName) + } + + name = tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + return nil + } + + deleteTemplate := "https://{{region}}-aiplatform.googleapis.com/v1beta1/projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}" + + url, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + deletionerror = err + } + url = url + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", url, err) + deletionerror = err + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + + return deletionerror +} diff --git a/website/docs/list-resources/google_vertex_ai_rag_corpus.html.markdown b/website/docs/list-resources/google_vertex_ai_rag_corpus.html.markdown new file mode 100644 index 0000000000..c00a67604a --- /dev/null +++ b/website/docs/list-resources/google_vertex_ai_rag_corpus.html.markdown @@ -0,0 +1,52 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This code is generated by Magic Modules using the following: +# +# Configuration: https:#github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/RagCorpus.yaml +# Template: https:#github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/list_resource.html.markdown.tmpl +# +# DO NOT EDIT this file directly. Any changes made to this file will be +# overwritten during the next generation cycle. +# +# ---------------------------------------------------------------------------- +subcategory: "Vertex AI" +description: |- + List Vertex AI ragcorpus resources in a project for use with terraform query + and .tfquery.hcl files. +--- + +# google_vertex_ai_rag_corpus (list) + +Lists [`google_vertex_ai_rag_corpus`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_vertex_ai_rag_corpus) resources for use with [`terraform query`](https://developer.hashicorp.com/terraform/cli/commands/query) and **`.tfquery.hcl`** files. + +For how list resources work in this provider, file layout, Terraform version requirements, and shared `list` block arguments, refer to the guide [Use list resources with terraform query (Google Cloud provider)](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/using_list_resources_with_terraform_query). + +## Example + +```hcl +list "google_vertex_ai_rag_corpus" "all" { + provider = google + + config { + region = "..." + project = "..." # Optional + } +} +``` + +Run `terraform query` from the directory that contains the `.tfquery.hcl` file. + +## Configuration (`config` block) +* `region` - (Required) The region of the RagCorpus. eg europe-west4 +* `project` - (Optional) + +## Results + +By default each result includes **resource identity** for [`google_vertex_ai_rag_corpus`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_vertex_ai_rag_corpus) (see [Resource identity](https://developer.hashicorp.com/terraform/language/block/import#identity)). + +With `include_resource = true` on the `list` block, results also include the full resource-style attributes documented for the managed [`google_vertex_ai_rag_corpus` resource](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_vertex_ai_rag_corpus#attributes-reference). diff --git a/website/docs/r/vertex_ai_rag_corpus.html.markdown b/website/docs/r/vertex_ai_rag_corpus.html.markdown new file mode 100644 index 0000000000..e11a3b8be5 --- /dev/null +++ b/website/docs/r/vertex_ai_rag_corpus.html.markdown @@ -0,0 +1,296 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This code is generated by Magic Modules using the following: +# +# Configuration: https:#github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/RagCorpus.yaml +# Template: https:#github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/resource.html.markdown.tmpl +# +# DO NOT EDIT this file directly. Any changes made to this file will be +# overwritten during the next generation cycle. +# +# ---------------------------------------------------------------------------- +subcategory: "Vertex AI" +description: |- + A RAG corpus is a container for user data uploaded to Vertex AI RAG Engine for chunking, embedding, and indexing. +--- + +# google_vertex_ai_rag_corpus + +A RAG corpus is a container for user data uploaded to Vertex AI RAG Engine for chunking, embedding, and indexing. + + +To get more information about RagCorpus, see: + +* [API documentation](https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/rest/v1/projects.locations.ragCorpora) +* How-to Guides + * [Manage your RAG corpus](https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/rag-engine/manage-your-rag-corpus) + + +## Example Usage - Vertex Ai Rag Corpus Basic + + +```hcl +resource "google_vertex_ai_rag_corpus" "example" { + display_name = "rag-corpus" + description = "A basic RAG corpus" + region = "europe-west4" + + vector_db_config { + rag_managed_db { + knn {} + } + + rag_embedding_model_config { + vertex_prediction_endpoint { + endpoint = "projects/${data.google_project.project.number}/locations/europe-west4/publishers/google/models/text-embedding-005" + } + } + } +} + +data "google_project" "project" { +} +``` + +## Example Usage - Vertex Ai Rag Corpus Full + + +```hcl +resource "google_vertex_ai_rag_corpus" "example" { + display_name = "rag-corpus-full" + description = "A RAG corpus with a customer-managed encryption key" + region = "europe-west4" + + vector_db_config { + rag_managed_db { + ann { + tree_depth = 2 + leaf_count = 500 + } + } + + rag_embedding_model_config { + vertex_prediction_endpoint { + endpoint = "projects/${data.google_project.project.number}/locations/europe-west4/publishers/google/models/text-embedding-005" + } + } + } + + encryption_spec { + kms_key_name = "kms-key" + } +} + +data "google_project" "project" { +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `display_name` - + (Required) + Required. The display name of the RagCorpus. The name can be up to 128 + characters long and can consist of any UTF-8 characters. + +* `region` - + (Required) + The region of the RagCorpus. eg europe-west4 + + +* `description` - + (Optional) + Optional. The description of the RagCorpus. + +* `vector_db_config` - + (Optional) + Optional. Immutable. The config for the RAG-managed Vector DB. + Structure is [documented below](#nested_vector_db_config). + +* `encryption_spec` - + (Optional) + Optional. Immutable. The CMEK key name used to encrypt at-rest data + related to this corpus. Only applicable to RagManagedDb option for Vector + DB. This field can only be set at corpus creation time, and cannot be + updated or deleted. + Structure is [documented below](#nested_encryption_spec). + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + +* `deletion_policy` - (Optional) Whether Terraform will be prevented from destroying the resource. Defaults to DELETE. + When a 'terraform destroy' or 'terraform apply' would delete the resource, + the command will fail if this field is set to "PREVENT" in Terraform state. + When set to "ABANDON", the command will remove the resource from Terraform + management without updating or deleting the resource in the API. + When set to "DELETE", deleting the resource is allowed. + + +The `vector_db_config` block supports: + +* `rag_managed_db` - + (Optional) + The config for the default RAG-managed Vector DB. + Structure is [documented below](#nested_vector_db_config_rag_managed_db). + +* `rag_embedding_model_config` - + (Optional) + Optional. Immutable. The embedding model config of the Vector DB. + Structure is [documented below](#nested_vector_db_config_rag_embedding_model_config). + + +The `rag_managed_db` block supports: + +* `knn` - + (Optional) + Performs a KNN search on RagCorpus. This is the default choice if not specified. + +* `ann` - + (Optional) + Performs an ANN search on RagCorpus. + Structure is [documented below](#nested_vector_db_config_rag_managed_db_ann). + + +The `ann` block supports: + +* `tree_depth` - + (Optional) + The depth of the tree-based structure. Only depth values of 2 and 3 are supported. Default value is 2. + +* `leaf_count` - + (Optional) + Number of leaf nodes in the tree-based structure. Default value is 500. + +The `rag_embedding_model_config` block supports: + +* `vertex_prediction_endpoint` - + (Optional) + The Vertex AI Prediction Endpoint used for dense vector search. + Structure is [documented below](#nested_vector_db_config_rag_embedding_model_config_vertex_prediction_endpoint). + + +The `vertex_prediction_endpoint` block supports: + +* `endpoint` - + (Required) + Required. The endpoint resource name. Format: + projects/{project}/locations/{location}/publishers/{publisher}/models/{model} + or projects/{project}/locations/{location}/endpoints/{endpoint}. + +* `model` - + (Output) + Output only. The resource name of the model that is deployed on the endpoint. + +* `model_version_id` - + (Output) + Output only. Version ID of the model that is deployed on the endpoint. + +The `encryption_spec` block supports: + +* `kms_key_name` - + (Required) + Required. The Cloud KMS resource identifier of the customer managed + encryption key used to protect the resource. Has the form: + projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key. + The key needs to be in the same region as where the resource is + created. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}` + +* `name` - + The generated name of the RagCorpus, in the format + projects/{project}/locations/{location}/ragCorpora/{rag_corpus}. + +* `create_time` - + Output only. Timestamp when this RagCorpus was created. + +* `update_time` - + Output only. Timestamp when this RagCorpus was last updated. + +* `corpus_status` - + Output only. RagCorpus state. + Structure is [documented below](#nested_corpus_status). + + +The `corpus_status` block contains: + +* `state` - + (Output) + Output only. RagCorpus life state. + +* `error_status` - + (Output) + Output only. Only populated when the state is ERROR. + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +RagCorpus can be imported using any of these accepted formats: + +* `projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}` +* `{{project}}/{{region}}/{{name}}` +* `{{region}}/{{name}}` +* `{{name}}` + +In Terraform v1.12.0 and later, use an [`identity` block](https://developer.hashicorp.com/terraform/language/block/import#identity) to import RagCorpus using identity values. For example: + +```tf +import { + identity = { + name = "<-optional value->" + region = "<-required value->" + project = "<-optional value->" + } + to = google_vertex_ai_rag_corpus.default +} +``` + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import RagCorpus using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/locations/{{region}}/ragCorpora/{{name}}" + to = google_vertex_ai_rag_corpus.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), RagCorpus can be imported using one of the formats above. For example: + +``` +$ terraform import google_vertex_ai_rag_corpus.default projects/{{project}}/locations/{{region}}/ragCorpora/{{name}} +$ terraform import google_vertex_ai_rag_corpus.default {{project}}/{{region}}/{{name}} +$ terraform import google_vertex_ai_rag_corpus.default {{region}}/{{name}} +$ terraform import google_vertex_ai_rag_corpus.default {{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override).