diff --git a/google/services/compute/resource_compute_disk.go b/google/services/compute/resource_compute_disk.go index f4b1b042054..1547aebac4d 100644 --- a/google/services/compute/resource_compute_disk.go +++ b/google/services/compute/resource_compute_disk.go @@ -635,6 +635,16 @@ encryption key that protects this resource.`, }, }, }, + "storage_pool": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareResourceNames, + Description: `The URL of the storage pool in which the new disk is created. +For example: +* https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/storagePools/{storagePool} +* /projects/{project}/zones/{zone}/storagePools/{storagePool}`, + }, "type": { Type: schema.TypeString, Optional: true, @@ -847,6 +857,12 @@ func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error { } else if v, ok := d.GetOkExists("licenses"); !tpgresource.IsEmptyValue(reflect.ValueOf(licensesProp)) && (ok || !reflect.DeepEqual(v, licensesProp)) { obj["licenses"] = licensesProp } + storagePoolProp, err := expandComputeDiskStoragePool(d.Get("storage_pool"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("storage_pool"); !tpgresource.IsEmptyValue(reflect.ValueOf(storagePoolProp)) && (ok || !reflect.DeepEqual(v, storagePoolProp)) { + obj["storagePool"] = storagePoolProp + } labelsProp, err := expandComputeDiskEffectiveLabels(d.Get("effective_labels"), d, config) if err != nil { return err @@ -1062,6 +1078,9 @@ func resourceComputeDiskRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("licenses", flattenComputeDiskLicenses(res["licenses"], d, config)); err != nil { return fmt.Errorf("Error reading Disk: %s", err) } + if err := d.Set("storage_pool", flattenComputeDiskStoragePool(res["storagePool"], d, config)); err != nil { + return fmt.Errorf("Error reading Disk: %s", err) + } if err := d.Set("terraform_labels", flattenComputeDiskTerraformLabels(res["labels"], d, config)); err != nil { return fmt.Errorf("Error reading Disk: %s", err) } @@ -1650,6 +1669,13 @@ func flattenComputeDiskLicenses(v interface{}, d *schema.ResourceData, config *t return tpgresource.ConvertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1) } +func flattenComputeDiskStoragePool(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return tpgresource.NameFromSelfLinkStateFunc(v) +} + func flattenComputeDiskTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return v @@ -1916,6 +1942,10 @@ func expandComputeDiskLicenses(v interface{}, d tpgresource.TerraformResourceDat return req, nil } +func expandComputeDiskStoragePool(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandComputeDiskEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { if v == nil { return map[string]string{}, nil diff --git a/google/services/compute/resource_compute_disk_test.go b/google/services/compute/resource_compute_disk_test.go index 798ff01e954..9e6d3f6073f 100644 --- a/google/services/compute/resource_compute_disk_test.go +++ b/google/services/compute/resource_compute_disk_test.go @@ -4,14 +4,17 @@ package compute_test import ( "fmt" + "net/http" "os" "testing" + "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "google.golang.org/api/compute/v1" ) @@ -1384,3 +1387,110 @@ resource "google_compute_disk" "foobar" { } `, add, strategy, diskName) } + +func TestAccComputeDisk_storagePoolSpecified(t *testing.T) { + t.Parallel() + + storagePoolName := fmt.Sprintf("tf-test-storage-pool-%s", acctest.RandString(t, 10)) + storagePoolUrl := fmt.Sprintf("/projects/%s/zones/%s/storagePools/%s", envvar.GetTestProjectFromEnv(), envvar.GetTestZoneFromEnv(), storagePoolName) + diskName := fmt.Sprintf("tf-test-disk-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + PreConfig: setupTestingStoragePool(t, storagePoolName), + Config: testAccComputeDisk_storagePoolSpecified(diskName, storagePoolUrl), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_disk.foobar", "storage_pool", storagePoolName), + ), + }, + { + ResourceName: "google_compute_disk.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + + cleanupTestingStoragePool(t, storagePoolName) +} + +func setupTestingStoragePool(t *testing.T, storagePoolName string) func() { + return func() { + config := acctest.GoogleProviderConfig(t) + headers := make(http.Header) + project := envvar.GetTestProjectFromEnv() + zone := envvar.GetTestZoneFromEnv() + url := fmt.Sprintf("%sprojects/%s/zones/%s/storagePools", config.ComputeBasePath, project, zone) + storagePoolTypeUrl := fmt.Sprintf("/projects/%s/zones/%s/storagePoolTypes/hyperdisk-throughput", project, zone) + defaultTimeout := 20 * time.Minute + obj := make(map[string]interface{}) + obj["name"] = storagePoolName + obj["poolProvisionedCapacityGb"] = 10240 + obj["poolProvisionedThroughput"] = 180 + obj["storagePoolType"] = storagePoolTypeUrl + obj["capacityProvisioningType"] = "ADVANCED" + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: config.UserAgent, + Body: obj, + Timeout: defaultTimeout, + Headers: headers, + }) + if err != nil { + t.Errorf("Error creating StoragePool: %s", err) + } + + err = tpgcompute.ComputeOperationWaitTime(config, res, project, "Creating StoragePool", config.UserAgent, defaultTimeout) + if err != nil { + t.Errorf("Error waiting to create StoragePool: %s", err) + } + } +} + +func cleanupTestingStoragePool(t *testing.T, storagePoolName string) { + config := acctest.GoogleProviderConfig(t) + headers := make(http.Header) + project := envvar.GetTestProjectFromEnv() + zone := envvar.GetTestZoneFromEnv() + url := fmt.Sprintf("%sprojects/%s/zones/%s/storagePools/%s", config.ComputeBasePath, project, zone, storagePoolName) + defaultTimeout := 20 * time.Minute + var obj map[string]interface{} + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: project, + RawURL: url, + UserAgent: config.UserAgent, + Body: obj, + Timeout: defaultTimeout, + Headers: headers, + }) + if err != nil { + t.Errorf("Error deleting StoragePool: %s", err) + } + + err = tpgcompute.ComputeOperationWaitTime(config, res, project, "Deleting StoragePool", config.UserAgent, defaultTimeout) + if err != nil { + t.Errorf("Error waiting to delete StoragePool: %s", err) + } +} + +func testAccComputeDisk_storagePoolSpecified(diskName, storagePoolUrl string) string { + return fmt.Sprintf(` +resource "google_compute_disk" "foobar" { + name = "%s" + type = "hyperdisk-throughput" + size = 2048 + provisioned_throughput = 140 + storage_pool = "%s" +} +`, diskName, storagePoolUrl) +} diff --git a/website/docs/r/compute_disk.html.markdown b/website/docs/r/compute_disk.html.markdown index f8723703479..71c68faa205 100644 --- a/website/docs/r/compute_disk.html.markdown +++ b/website/docs/r/compute_disk.html.markdown @@ -263,6 +263,13 @@ The following arguments are supported: (Optional) Any applicable license URI. +* `storage_pool` - + (Optional) + The URL of the storage pool in which the new disk is created. + For example: + * https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/storagePools/{storagePool} + * /projects/{project}/zones/{zone}/storagePools/{storagePool} + * `zone` - (Optional) A reference to the zone where the disk resides.