diff --git a/.changelog/16088.txt b/.changelog/16088.txt new file mode 100644 index 00000000000..9be084b2e6a --- /dev/null +++ b/.changelog/16088.txt @@ -0,0 +1,7 @@ +```release-note:new-resource +`google_vmwareengine_datastore` +``` + +```release-note:new-datasource +`google_vmwareengine_datastore` +``` \ No newline at end of file diff --git a/google/provider/provider_mmv1_resources.go b/google/provider/provider_mmv1_resources.go index c30734bfbdc..554fefb84f5 100644 --- a/google/provider/provider_mmv1_resources.go +++ b/google/provider/provider_mmv1_resources.go @@ -454,6 +454,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), "google_vmwareengine_subnet": vmwareengine.DataSourceVmwareengineSubnet(), "google_vmwareengine_vcenter_credentials": vmwareengine.DataSourceVmwareengineVcenterCredentials(), + "google_vmwareengine_datastore": vmwareengine.DataSourceVmwareengineDatastore(), "google_compute_region_backend_service": compute.DataSourceGoogleComputeRegionBackendService(), "google_network_management_connectivity_test_run": networkmanagement.DataSourceGoogleNetworkManagementTestRun(), "google_network_management_connectivity_tests": networkmanagement.DataSourceGoogleNetworkManagementConnectivityTests(), @@ -591,9 +592,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{ } // Resources -// Generated resources: 708 +// Generated resources: 709 // Generated IAM resources: 327 -// Total generated resources: 1035 +// Total generated resources: 1036 var generatedResources = map[string]*schema.Resource{ "google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(), "google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(), @@ -1587,6 +1588,7 @@ var generatedResources = map[string]*schema.Resource{ "google_vertex_ai_reasoning_engine": vertexai.ResourceVertexAIReasoningEngine(), "google_vertex_ai_tensorboard": vertexai.ResourceVertexAITensorboard(), "google_vmwareengine_cluster": vmwareengine.ResourceVmwareengineCluster(), + "google_vmwareengine_datastore": vmwareengine.ResourceVmwareengineDatastore(), "google_vmwareengine_external_access_rule": vmwareengine.ResourceVmwareengineExternalAccessRule(), "google_vmwareengine_external_address": vmwareengine.ResourceVmwareengineExternalAddress(), "google_vmwareengine_network": vmwareengine.ResourceVmwareengineNetwork(), diff --git a/google/services/vmwareengine/data_source_vmwareengine_datastore.go b/google/services/vmwareengine/data_source_vmwareengine_datastore.go new file mode 100644 index 00000000000..c20679b517e --- /dev/null +++ b/google/services/vmwareengine/data_source_vmwareengine_datastore.go @@ -0,0 +1,109 @@ +// Copyright (c) HashiCorp, Inc. +// 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/vmwareengine/Datastore.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/datasource.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- +package vmwareengine + +import ( + "fmt" + "log" + "net/http" + "reflect" + "regexp" + "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/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/verify" + + "google.golang.org/api/googleapi" +) + +var ( + _ = fmt.Sprintf + _ = log.Print + _ = http.Get + _ = reflect.ValueOf + _ = regexp.Match + _ = 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 DataSourceVmwareengineDatastore() *schema.Resource { + rs := ResourceVmwareengineDatastore().Schema + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(rs) + + tpgresource.AddRequiredFieldsToSchema(dsSchema, "location", "name") + + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + + return &schema.Resource{ + Read: dataSourceVmwareengineDatastoreRead, + Schema: dsSchema, + } +} + +func dataSourceVmwareengineDatastoreRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/datastores/{{name}}") + if err != nil { + return err + } + + d.SetId(id) + + err = resourceVmwareengineDatastoreRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil +} diff --git a/google/services/vmwareengine/resource_vmwareengine_datastore.go b/google/services/vmwareengine/resource_vmwareengine_datastore.go new file mode 100644 index 00000000000..02370560299 --- /dev/null +++ b/google/services/vmwareengine/resource_vmwareengine_datastore.go @@ -0,0 +1,765 @@ +// Copyright (c) HashiCorp, Inc. +// 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/vmwareengine/Datastore.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 vmwareengine + +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/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/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 ResourceVmwareengineDatastore() *schema.Resource { + return &schema.Resource{ + Create: resourceVmwareengineDatastoreCreate, + Read: resourceVmwareengineDatastoreRead, + Update: resourceVmwareengineDatastoreUpdate, + Delete: resourceVmwareengineDatastoreDelete, + + Importer: &schema.ResourceImporter{ + State: resourceVmwareengineDatastoreImport, + }, + + 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, + ), + + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Resource ID segment making up resource 'name'. It identifies the resource within its parent collection as described in https://google.aip.dev/122.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The user-provided identifier of the datastore to be created. +This identifier must be unique among each 'Datastore' within the parent +and becomes the final token in the name URI. +The identifier must meet the following requirements: + +* Only contains 1-63 alphanumeric characters and hyphens +* Begins with an alphabetical character +* Ends with a non-hyphen character +* Not formatted as a UUID +* Complies with [RFC 1034](https://datatracker.ietf.org/doc/html/rfc1034) +(section 3.5)`, + }, + "nfs_datastore": { + Type: schema.TypeList, + Required: true, + Description: `The NFS datastore configuration.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "google_file_service": { + Type: schema.TypeList, + Optional: true, + Description: `Google service file service configuration`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "filestore_instance": { + Type: schema.TypeString, + Optional: true, + Description: `Google filestore instance resource name +e.g. projects/my-project/locations/me-west1-b/instances/my-instance`, + }, + "netapp_volume": { + Type: schema.TypeString, + Optional: true, + Description: `Google netapp volume resource name +e.g. projects/my-project/locations/me-west1-b/volumes/my-volume`, + }, + }, + }, + }, + "third_party_file_service": { + Type: schema.TypeList, + Optional: true, + Description: `Third party file service configuration`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "file_share": { + Type: schema.TypeString, + Required: true, + Description: `Required +Mount Folder name`, + }, + "network": { + Type: schema.TypeString, + Required: true, + Description: `Required to identify vpc peering used for NFS access +network name of NFS's vpc +e.g. projects/project-id/global/networks/my-network_id`, + }, + "servers": { + Type: schema.TypeList, + Required: true, + Description: `Server IP addresses of the NFS file service. +NFS v3, provide a single IP address or DNS name. +Multiple servers can be supported in future when NFS 4.1 protocol support +is enabled.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `User-provided description for this datastore`, + }, + "clusters": { + Type: schema.TypeList, + Computed: true, + Description: `Clusters to which the datastore is attached.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Creation time of this resource.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The state of the Datastore. +Possible values: +CREATING +ACTIVE +UPDATING +DELETING +SOFT_DELETING +SOFT_DELETED`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `System-generated unique identifier for the resource.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Last update time of this resource.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceVmwareengineDatastoreCreate(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{}) + descriptionProp, err := expandVmwareengineDatastoreDescription(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 + } + nfsDatastoreProp, err := expandVmwareengineDatastoreNfsDatastore(d.Get("nfs_datastore"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("nfs_datastore"); !tpgresource.IsEmptyValue(reflect.ValueOf(nfsDatastoreProp)) && (ok || !reflect.DeepEqual(v, nfsDatastoreProp)) { + obj["nfsDatastore"] = nfsDatastoreProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{VmwareengineBasePath}}projects/{{project}}/locations/{{location}}/datastores?datastoreId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new Datastore: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Datastore: %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 Datastore: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/datastores/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = VmwareengineOperationWaitTime( + config, res, project, "Creating Datastore", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create Datastore: %s", err) + } + + log.Printf("[DEBUG] Finished creating Datastore %q: %#v", d.Id(), res) + + return resourceVmwareengineDatastoreRead(d, meta) +} + +func resourceVmwareengineDatastoreRead(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, "{{VmwareengineBasePath}}projects/{{project}}/locations/{{location}}/datastores/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Datastore: %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("VmwareengineDatastore %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + + if err := d.Set("clusters", flattenVmwareengineDatastoreClusters(res["clusters"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + if err := d.Set("create_time", flattenVmwareengineDatastoreCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + if err := d.Set("description", flattenVmwareengineDatastoreDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + if err := d.Set("nfs_datastore", flattenVmwareengineDatastoreNfsDatastore(res["nfsDatastore"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + if err := d.Set("state", flattenVmwareengineDatastoreState(res["state"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + if err := d.Set("uid", flattenVmwareengineDatastoreUid(res["uid"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + if err := d.Set("update_time", flattenVmwareengineDatastoreUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading Datastore: %s", err) + } + + return nil +} + +func resourceVmwareengineDatastoreUpdate(d *schema.ResourceData, meta interface{}) error { + 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 Datastore: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandVmwareengineDatastoreDescription(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 + } + nfsDatastoreProp, err := expandVmwareengineDatastoreNfsDatastore(d.Get("nfs_datastore"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("nfs_datastore"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nfsDatastoreProp)) { + obj["nfsDatastore"] = nfsDatastoreProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{VmwareengineBasePath}}projects/{{project}}/locations/{{location}}/datastores/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating Datastore %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("nfs_datastore") { + updateMask = append(updateMask, "nfsDatastore") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + 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 Datastore %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating Datastore %q: %#v", d.Id(), res) + } + + err = VmwareengineOperationWaitTime( + config, res, project, "Updating Datastore", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceVmwareengineDatastoreRead(d, meta) +} + +func resourceVmwareengineDatastoreDelete(d *schema.ResourceData, meta interface{}) error { + 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 Datastore: %s", err) + } + billingProject = project + + url, err := tpgresource.ReplaceVars(d, config, "{{VmwareengineBasePath}}projects/{{project}}/locations/{{location}}/datastores/{{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 Datastore %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, "Datastore") + } + + err = VmwareengineOperationWaitTime( + config, res, project, "Deleting Datastore", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting Datastore %q: %#v", d.Id(), res) + return nil +} + +func resourceVmwareengineDatastoreImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/locations/(?P[^/]+)/datastores/(?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/{{location}}/datastores/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenVmwareengineDatastoreClusters(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreNfsDatastore(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["google_file_service"] = + flattenVmwareengineDatastoreNfsDatastoreGoogleFileService(original["googleFileService"], d, config) + transformed["third_party_file_service"] = + flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileService(original["thirdPartyFileService"], d, config) + return []interface{}{transformed} +} +func flattenVmwareengineDatastoreNfsDatastoreGoogleFileService(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["filestore_instance"] = + flattenVmwareengineDatastoreNfsDatastoreGoogleFileServiceFilestoreInstance(original["filestoreInstance"], d, config) + transformed["netapp_volume"] = + flattenVmwareengineDatastoreNfsDatastoreGoogleFileServiceNetappVolume(original["netappVolume"], d, config) + return []interface{}{transformed} +} +func flattenVmwareengineDatastoreNfsDatastoreGoogleFileServiceFilestoreInstance(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreNfsDatastoreGoogleFileServiceNetappVolume(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileService(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["file_share"] = + flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceFileShare(original["fileShare"], d, config) + transformed["network"] = + flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceNetwork(original["network"], d, config) + transformed["servers"] = + flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceServers(original["servers"], d, config) + return []interface{}{transformed} +} +func flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceFileShare(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceServers(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreUid(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineDatastoreUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandVmwareengineDatastoreDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVmwareengineDatastoreNfsDatastore(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{}) + + transformedGoogleFileService, err := expandVmwareengineDatastoreNfsDatastoreGoogleFileService(original["google_file_service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGoogleFileService); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["googleFileService"] = transformedGoogleFileService + } + + transformedThirdPartyFileService, err := expandVmwareengineDatastoreNfsDatastoreThirdPartyFileService(original["third_party_file_service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedThirdPartyFileService); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["thirdPartyFileService"] = transformedThirdPartyFileService + } + + return transformed, nil +} + +func expandVmwareengineDatastoreNfsDatastoreGoogleFileService(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{}) + + transformedFilestoreInstance, err := expandVmwareengineDatastoreNfsDatastoreGoogleFileServiceFilestoreInstance(original["filestore_instance"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFilestoreInstance); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["filestoreInstance"] = transformedFilestoreInstance + } + + transformedNetappVolume, err := expandVmwareengineDatastoreNfsDatastoreGoogleFileServiceNetappVolume(original["netapp_volume"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetappVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["netappVolume"] = transformedNetappVolume + } + + return transformed, nil +} + +func expandVmwareengineDatastoreNfsDatastoreGoogleFileServiceFilestoreInstance(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVmwareengineDatastoreNfsDatastoreGoogleFileServiceNetappVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVmwareengineDatastoreNfsDatastoreThirdPartyFileService(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{}) + + transformedFileShare, err := expandVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceFileShare(original["file_share"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFileShare); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["fileShare"] = transformedFileShare + } + + transformedNetwork, err := expandVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedServers, err := expandVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceServers(original["servers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServers); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["servers"] = transformedServers + } + + return transformed, nil +} + +func expandVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceFileShare(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVmwareengineDatastoreNfsDatastoreThirdPartyFileServiceServers(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google/services/vmwareengine/resource_vmwareengine_datastore_generated_meta.yaml b/google/services/vmwareengine/resource_vmwareengine_datastore_generated_meta.yaml new file mode 100644 index 00000000000..f1ddbd95eca --- /dev/null +++ b/google/services/vmwareengine/resource_vmwareengine_datastore_generated_meta.yaml @@ -0,0 +1,23 @@ +resource: google_vmwareengine_datastore +generation_type: mmv1 +source_file: products/vmwareengine/Datastore.yaml +api_service_name: vmwareengine.googleapis.com +api_version: v1 +api_resource_type_kind: Datastore +autogen_status: true +fields: + - api_field: clusters + - api_field: createTime + - api_field: description + - field: location + provider_only: true + - field: name + provider_only: true + - api_field: nfsDatastore.googleFileService.filestoreInstance + - api_field: nfsDatastore.googleFileService.netappVolume + - api_field: nfsDatastore.thirdPartyFileService.fileShare + - api_field: nfsDatastore.thirdPartyFileService.network + - api_field: nfsDatastore.thirdPartyFileService.servers + - api_field: state + - api_field: uid + - api_field: updateTime diff --git a/google/services/vmwareengine/resource_vmwareengine_datastore_sweeper.go b/google/services/vmwareengine/resource_vmwareengine_datastore_sweeper.go new file mode 100644 index 00000000000..8601bc779f6 --- /dev/null +++ b/google/services/vmwareengine/resource_vmwareengine_datastore_sweeper.go @@ -0,0 +1,223 @@ +// Copyright (c) HashiCorp, Inc. +// 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/vmwareengine/Datastore.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 vmwareengine + +import ( + "context" + "fmt" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + // Initialize base sweeper object + s := &sweeper.Sweeper{ + Name: "google_vmwareengine_datastore", + ListAndAction: listAndActionVmwareengineDatastore, + DeleteFunction: testSweepVmwareengineDatastore, + } + + // Register the sweeper + sweeper.AddTestSweepers(s) +} + +func testSweepVmwareengineDatastore(_ string) error { + return listAndActionVmwareengineDatastore(deleteResourceVmwareengineDatastore) +} + +func listAndActionVmwareengineDatastore(action sweeper.ResourceAction) error { + var lastError error + resourceName := "VmwareengineDatastore" + 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://vmwareengine.googleapis.com/v1/projects/{{project}}/locations/{{location}}/datastores", "?")[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["datastores"] + if ok { + log.Printf("[INFO][SWEEPER_LOG] Found resources under expected key 'datastores'") + } 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 deleteResourceVmwareengineDatastore(config *transport_tpg.Config, d *tpgresource.ResourceDataMock, obj map[string]interface{}) error { + var deletionerror error + resourceName := "VmwareengineDatastore" + 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://vmwareengine.googleapis.com/v1/projects/{{project}}/locations/{{location}}/datastores/{{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/google/services/vmwareengine/resource_vmwareengine_datastore_test.go b/google/services/vmwareengine/resource_vmwareengine_datastore_test.go new file mode 100644 index 00000000000..3d6f5f32cd8 --- /dev/null +++ b/google/services/vmwareengine/resource_vmwareengine_datastore_test.go @@ -0,0 +1,310 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: Handwritten *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Source file: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_datastore_test.go +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- +package vmwareengine_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccVmwareengineDatastore_vmwareEngineDatastoreThirdparty_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "region": envvar.GetTestRegionFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineDatastoreDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreThirdparty(context, "test description"), + }, + { + ResourceName: "google_vmwareengine_datastore.example_thirdparty", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreThirdparty(context, "updated test description"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("google_vmwareengine_datastore.example_thirdparty", plancheck.ResourceActionUpdate), + }, + }, + }, + }, + }) +} + +func testAccVmwareengineDatastore_vmwareEngineDatastoreThirdparty(context map[string]interface{}, description string) string { + context["description"] = description + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "default" + provider = google +} + +resource "google_vmwareengine_datastore" "example_thirdparty" { + name = "tf-test-thirdparty-datastore%{random_suffix}" + location = "%{region}-a" + description = "%{description}" + + nfs_datastore { + third_party_file_service { + file_share = "/share1" + network = data.google_compute_network.default.id + servers = ["10.0.0.4"] + } + } +} +`, context) +} + +func TestAccVmwareengineDatastore_vmwareEngineDatastoreFilestore_update(t *testing.T) { + t.Parallel() + acctest.BootstrapIamMembers(t, []acctest.IamMember{ + { + Member: "serviceAccount:service-{project_number}@gcp-sa-vmwareengine.iam.gserviceaccount.com", + Role: "roles/file.viewer", + }, + }) + + context := map[string]interface{}{ + "region": envvar.GetTestRegionFromEnv(), + "zone": envvar.GetTestZoneFromEnv(), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "datastore-test"), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineDatastoreDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreFilestore(context, true, "example google_file_service.filestore datastore."), + }, + { + ResourceName: "google_vmwareengine_datastore.example_filestore", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name"}, + }, + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreFilestore(context, true, "updated example google_file_service.filestore datastore."), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("google_vmwareengine_datastore.example_filestore", plancheck.ResourceActionUpdate), + }, + }, + }, + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreFilestore(context, false, "updated example google_file_service.filestore datastore."), + }, + }, + }) +} + +func testAccVmwareengineDatastore_vmwareEngineDatastoreFilestore(context map[string]interface{}, delete_protection bool, description string) string { + context["delete_protection"] = delete_protection + context["description"] = description + return acctest.Nprintf(` +# Use existing network with address created and PSA enabled. +data "google_compute_network" "test_network" { + name = "%{network_name}" +} + +# Create a filestore instance with delete protection enabled +resource "google_filestore_instance" "test_instance" { + name = "tf-test-datastore-fs-instance%{random_suffix}" + location = "%{zone}" + tier = "ZONAL" + deletion_protection_enabled = "%{delete_protection}" + + file_shares { + capacity_gb = 1024 + name = "share1" + } + + networks { + network = data.google_compute_network.test_network.id + modes = ["MODE_IPV4"] + connect_mode = "PRIVATE_SERVICE_ACCESS" + } +} + +# Create a VmwareEngine Datastore, referencing the filestore instance +resource "google_vmwareengine_datastore" "example_filestore" { + name = "tf-test-filestore-datastore%{random_suffix}" + location = "%{zone}" + description = "%{description}" + + nfs_datastore { + google_file_service { + filestore_instance = google_filestore_instance.test_instance.id + } + } +} +`, context) +} + +func TestAccVmwareengineDatastore_vmwareEngineDatastoreNetapp_update(t *testing.T) { + t.Parallel() + acctest.BootstrapIamMembers(t, []acctest.IamMember{ + { + Member: "serviceAccount:service-{project_number}@gcp-sa-vmwareengine.iam.gserviceaccount.com", + Role: "roles/netapp.viewer", + }, + }) + + context := map[string]interface{}{ + "region": envvar.GetTestRegionFromEnv(), + "zone": envvar.GetTestZoneFromEnv(), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "datastore-test", acctest.ServiceNetworkWithParentService("netapp.servicenetworking.goog")), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineDatastoreDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreNetapp(context, "example google_file_service.netapp datastore."), + }, + { + ResourceName: "google_vmwareengine_datastore.example_netapp", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name"}, + }, + { + Config: testAccVmwareengineDatastore_vmwareEngineDatastoreNetapp(context, "updated example google_file_service.netapp datastore."), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("google_vmwareengine_datastore.example_netapp", plancheck.ResourceActionUpdate), + }, + }, + }, + }, + }) +} + +func testAccVmwareengineDatastore_vmwareEngineDatastoreNetapp(context map[string]interface{}, description string) string { + context["description"] = description + return acctest.Nprintf(` +# Create a network or use datasource to reference existing network +data "google_compute_network" "vpc_network" { + name = "%{network_name}" +} + +# Create a Netapp storage pool +resource "google_netapp_storage_pool" "test_pool" { + name = "tf-test-netapp-storage-pool%{random_suffix}" + location = "%{region}" + zone = "%{region}-b" + replica_zone = "%{region}-a" + service_level = "FLEX" + capacity_gib = "2048" + network = data.google_compute_network.vpc_network.id + lifecycle { + ignore_changes = [ + qos_type, + ] + } +} + +# Create a netapp volume +resource "google_netapp_volume" "test_volume" { + location = "%{region}" + name = "tf-test-netapp-volume%{random_suffix}" + capacity_gib = "1024" + share_name = "share1" + storage_pool = google_netapp_storage_pool.test_pool.name + protocols = [ "NFSV3" ] + deletion_policy = "DEFAULT" + restricted_actions = [ "DELETE" ] +} + +# Create a VmwareEngine Datastore, referencing the netapp volume +resource "google_vmwareengine_datastore" "example_netapp" { + name = "tf-test-netapp-datastore%{random_suffix}" + location = "%{region}" + description = "%{description}" + + nfs_datastore { + google_file_service { + netapp_volume = google_netapp_volume.test_volume.id + } + } +} +`, context) +} + +func testAccCheckVmwareengineDatastoreDestroyProducer(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_vmwareengine_datastore" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{VmwareengineBasePath}}projects/{{project}}/locations/{{location}}/datastores/{{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("VmwareengineDatastore still exists at %s", url) + } + } + + return nil + } +} diff --git a/website/docs/d/vmwareengine_datastore_html.markdown b/website/docs/d/vmwareengine_datastore_html.markdown new file mode 100644 index 00000000000..84100502388 --- /dev/null +++ b/website/docs/d/vmwareengine_datastore_html.markdown @@ -0,0 +1,46 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: Handwritten *** +# +# ---------------------------------------------------------------------------- +# +# This code is generated by Magic Modules using the following: +# +# Source file: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/d/vmwareengine_datastore_html.markdown +# +# DO NOT EDIT this file directly. Any changes made to this file will be +# overwritten during the next generation cycle. +# +# ---------------------------------------------------------------------------- +subcategory: "Cloud VMware Engine" +description: |- + Get information about a datastore. +--- + +# google\_vmwareengine\_datastore + +Use this data source to get details about a datastore resource. + +To get more information about datastore, see: +* [API documentation](https://docs.cloud.google.com/vmware-engine/docs/vmware-ecosystem/concepts-nfs-datastores-overview) + +## Example Usage + +```hcl +data "google_vmwareengine_datastore" "test_ds" { + name = "example-ds" + location = "us-west2" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the resource. +* `location` - (Required) either regional or zonal location of the resource. + +## Attributes Reference + +See [google_vmwareengine_datastore](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/vmwareengine_datastore#attributes-reference) resource for details of all the available attributes. diff --git a/website/docs/r/vmwareengine_datastore.html.markdown b/website/docs/r/vmwareengine_datastore.html.markdown new file mode 100644 index 00000000000..4bca9922eed --- /dev/null +++ b/website/docs/r/vmwareengine_datastore.html.markdown @@ -0,0 +1,248 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** 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/vmwareengine/Datastore.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: "Cloud VMware Engine" +description: |- + A datastore resource that can be mounted on a privatecloud cluster +--- + +# google_vmwareengine_datastore + +A datastore resource that can be mounted on a privatecloud cluster + + + +## Example Usage - Vmware Engine Datastore Thirdparty + + +```hcl +# use existing network with connectivity to the thirdparty datastore +data "google_compute_network" "default" { + name = "default" +} + +# create a thirdparty datastore +resource "google_vmwareengine_datastore" "example_thirdparty" { + name = "thirdparty-datastore" + location = "us-west1-a" + description = "example thirdparty datastore." + + nfs_datastore { + third_party_file_service { + file_share = "/share1" + network = data.google_compute_network.default.id + servers = ["10.0.0.4"] + } + } +} +``` +## Example Usage - Vmware Engine Datastore Filestore + + +```hcl +# Use existing filestore instance +data "google_filestore_instance" "test_instance" { + name = "fs-instance" + location = "" +} + +# Create a VmwareEngine Datastore, referencing the filestore instance +resource "google_vmwareengine_datastore" "example_filestore" { + name = "filestore-datastore" + location = "" + description = "example google_file_service.filestore datastore." + + nfs_datastore { + google_file_service { + filestore_instance = google_filestore_instance.test_instance.id + } + } +} +``` +## Example Usage - Vmware Engine Datastore Netapp + + +```hcl +# Use existing netapp volume +resource "google_netapp_volume" "test_volume" { + name = "netapp-volume" + location = "us-west1" +} + +# Create a VmwareEngine Datastore, referencing the netapp volume +resource "google_vmwareengine_datastore" "example_netapp" { + name = "netapp-datastore" + location = "us-west1" + description = "example google_file_service.netapp datastore." + + nfs_datastore { + google_file_service { + netapp_volume = google_netapp_volume.test_volume.id + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `nfs_datastore` - + (Required) + The NFS datastore configuration. + Structure is [documented below](#nested_nfs_datastore). + +* `location` - + (Required) + Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122. + +* `name` - + (Required) + The user-provided identifier of the datastore to be created. + This identifier must be unique among each `Datastore` within the parent + and becomes the final token in the name URI. + The identifier must meet the following requirements: + * Only contains 1-63 alphanumeric characters and hyphens + * Begins with an alphabetical character + * Ends with a non-hyphen character + * Not formatted as a UUID + * Complies with [RFC 1034](https://datatracker.ietf.org/doc/html/rfc1034) + (section 3.5) + + +* `description` - + (Optional) + User-provided description for this datastore + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + + +The `nfs_datastore` block supports: + +* `google_file_service` - + (Optional) + Google service file service configuration + Structure is [documented below](#nested_nfs_datastore_google_file_service). + +* `third_party_file_service` - + (Optional) + Third party file service configuration + Structure is [documented below](#nested_nfs_datastore_third_party_file_service). + + +The `google_file_service` block supports: + +* `filestore_instance` - + (Optional) + Google filestore instance resource name + e.g. projects/my-project/locations/me-west1-b/instances/my-instance + +* `netapp_volume` - + (Optional) + Google netapp volume resource name + e.g. projects/my-project/locations/me-west1-b/volumes/my-volume + +The `third_party_file_service` block supports: + +* `file_share` - + (Required) + Required + Mount Folder name + +* `network` - + (Required) + Required to identify vpc peering used for NFS access + network name of NFS's vpc + e.g. projects/project-id/global/networks/my-network_id + +* `servers` - + (Required) + Server IP addresses of the NFS file service. + NFS v3, provide a single IP address or DNS name. + Multiple servers can be supported in future when NFS 4.1 protocol support + is enabled. + +## 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/{{location}}/datastores/{{name}}` + +* `clusters` - + Clusters to which the datastore is attached. + +* `create_time` - + Creation time of this resource. + +* `state` - + The state of the Datastore. + Possible values: + CREATING + ACTIVE + UPDATING + DELETING + SOFT_DELETING + SOFT_DELETED + +* `uid` - + System-generated unique identifier for the resource. + +* `update_time` - + Last update time of this resource. + + +## 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 + + +Datastore can be imported using any of these accepted formats: + +* `projects/{{project}}/locations/{{location}}/datastores/{{name}}` +* `{{project}}/{{location}}/{{name}}` +* `{{location}}/{{name}}` + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Datastore using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/locations/{{location}}/datastores/{{name}}" + to = google_vmwareengine_datastore.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), Datastore can be imported using one of the formats above. For example: + +``` +$ terraform import google_vmwareengine_datastore.default projects/{{project}}/locations/{{location}}/datastores/{{name}} +$ terraform import google_vmwareengine_datastore.default {{project}}/{{location}}/{{name}} +$ terraform import google_vmwareengine_datastore.default {{location}}/{{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).