From 6e6975e70395c954c7824a900587fb00c2b86d7e Mon Sep 17 00:00:00 2001 From: The Magician Date: Tue, 21 Mar 2023 18:49:40 -0700 Subject: [PATCH] Enable 3000 GB Local SSDs in Terraform validation. (#7469) (#14061) Signed-off-by: Modular Magician --- .changelog/7469.txt | 3 + google/resource_compute_instance.go | 10 ++ google/resource_compute_instance_template.go | 16 ++- ...resource_compute_instance_template_test.go | 109 +++++++++++++++++- google/resource_compute_instance_test.go | 87 +++++++++++++- 5 files changed, 214 insertions(+), 11 deletions(-) create mode 100644 .changelog/7469.txt diff --git a/.changelog/7469.txt b/.changelog/7469.txt new file mode 100644 index 00000000000..12eca8ef887 --- /dev/null +++ b/.changelog/7469.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +compute: changed `disk_size_gb` allowable sizes for SCRATCH disks from 375 GB to [375, 3000] GB in `google_compute_instance_template` +``` diff --git a/google/resource_compute_instance.go b/google/resource_compute_instance.go index f8984a4aa76..611da4b1585 100644 --- a/google/resource_compute_instance.go +++ b/google/resource_compute_instance.go @@ -635,6 +635,14 @@ func ResourceComputeInstance() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"SCSI", "NVME"}, false), Description: `The disk interface used for attaching this disk. One of SCSI or NVME.`, }, + "size": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(375), + Default: 375, + Description: `The size of the disk in gigabytes. One of 375 or 3000.`, + }, }, }, }, @@ -2455,6 +2463,7 @@ func expandScratchDisks(d *schema.ResourceData, config *Config, project string) AutoDelete: true, Type: "SCRATCH", Interface: d.Get(fmt.Sprintf("scratch_disk.%d.interface", i)).(string), + DiskSizeGb: int64(d.Get(fmt.Sprintf("scratch_disk.%d.size", i)).(int)), InitializeParams: &compute.AttachedDiskInitializeParams{ DiskType: diskType.RelativeLink(), }, @@ -2467,6 +2476,7 @@ func expandScratchDisks(d *schema.ResourceData, config *Config, project string) func flattenScratchDisk(disk *compute.AttachedDisk) map[string]interface{} { result := map[string]interface{}{ "interface": disk.Interface, + "size": disk.DiskSizeGb, } return result } diff --git a/google/resource_compute_instance_template.go b/google/resource_compute_instance_template.go index f8801d51402..fd2b133a432 100644 --- a/google/resource_compute_instance_template.go +++ b/google/resource_compute_instance_template.go @@ -34,7 +34,8 @@ var ( } ) -var REQUIRED_SCRATCH_DISK_SIZE_GB = 375 +var DEFAULT_SCRATCH_DISK_SIZE_GB = 375 +var VALID_SCRATCH_DISK_SIZES_GB [2]int = [2]int{375, 3000} func ResourceComputeInstanceTemplate() *schema.Resource { return &schema.Resource{ @@ -132,7 +133,7 @@ func ResourceComputeInstanceTemplate() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - Description: `The size of the image in gigabytes. If not specified, it will inherit the size of its base image. For SCRATCH disks, the size must be exactly 375GB.`, + Description: `The size of the image in gigabytes. If not specified, it will inherit the size of its base image. For SCRATCH disks, the size must be one of 375 or 3000 GB, with a default of 375 GB.`, }, "disk_type": { @@ -902,8 +903,13 @@ func resourceComputeInstanceTemplateScratchDiskCustomizeDiffFunc(diff TerraformR } diskSize := diff.Get(fmt.Sprintf("disk.%d.disk_size_gb", i)).(int) - if typee == "SCRATCH" && diskSize != REQUIRED_SCRATCH_DISK_SIZE_GB { - return fmt.Errorf("SCRATCH disks must be exactly %dGB, disk %d is %d", REQUIRED_SCRATCH_DISK_SIZE_GB, i, diskSize) + if typee == "SCRATCH" && !(diskSize == 375 || diskSize == 3000) { // see VALID_SCRATCH_DISK_SIZES_GB + return fmt.Errorf("SCRATCH disks must be one of %v GB, disk %d is %d", VALID_SCRATCH_DISK_SIZES_GB, i, diskSize) + } + + interfacee := diff.Get(fmt.Sprintf("disk.%d.interface", i)).(string) + if typee == "SCRATCH" && diskSize == 3000 && interfacee != "NVME" { + return fmt.Errorf("SCRATCH disks with a size of 3000 GB must have an interface of NVME. disk %d has interface %s", i, interfacee) } } @@ -1234,7 +1240,7 @@ func flattenDisk(disk *compute.AttachedDisk, configDisk map[string]any, defaultP // The API does not return a disk size value for scratch disks. They can only be one size, // so we can assume that size here. if disk.InitializeParams.DiskSizeGb == 0 && disk.Type == "SCRATCH" { - diskMap["disk_size_gb"] = REQUIRED_SCRATCH_DISK_SIZE_GB + diskMap["disk_size_gb"] = DEFAULT_SCRATCH_DISK_SIZE_GB } else { diskMap["disk_size_gb"] = disk.InitializeParams.DiskSizeGb } diff --git a/google/resource_compute_instance_template_test.go b/google/resource_compute_instance_template_test.go index 14648a6f35b..b24d702654f 100644 --- a/google/resource_compute_instance_template_test.go +++ b/google/resource_compute_instance_template_test.go @@ -167,24 +167,42 @@ func TestComputeInstanceTemplate_scratchDiskSizeCustomizeDiff(t *testing.T) { Typee string // misspelled on purpose, type is a special symbol DiskType string DiskSize int + Interfacee string ExpectError bool }{ - "scratch disk correct size": { + "scratch disk correct size 1": { Typee: "SCRATCH", DiskType: "local-ssd", DiskSize: 375, + Interfacee: "NVME", + ExpectError: false, + }, + "scratch disk correct size 2": { + Typee: "SCRATCH", + DiskType: "local-ssd", + DiskSize: 3000, + Interfacee: "NVME", ExpectError: false, }, "scratch disk incorrect size": { Typee: "SCRATCH", DiskType: "local-ssd", DiskSize: 300, + Interfacee: "NVME", + ExpectError: true, + }, + "scratch disk incorrect interface": { + Typee: "SCRATCH", + DiskType: "local-ssd", + DiskSize: 3000, + Interfacee: "SCSI", ExpectError: true, }, "non-scratch disk": { Typee: "PERSISTENT", DiskType: "", DiskSize: 300, + Interfacee: "NVME", ExpectError: false, }, } @@ -196,6 +214,7 @@ func TestComputeInstanceTemplate_scratchDiskSizeCustomizeDiff(t *testing.T) { "disk.0.type": tc.Typee, "disk.0.disk_type": tc.DiskType, "disk.0.disk_size_gb": tc.DiskSize, + "disk.0.interface": tc.Interfacee, }, } err := resourceComputeInstanceTemplateScratchDiskCustomizeDiffFunc(d) @@ -953,7 +972,27 @@ func TestAccComputeInstanceTemplate_withScratchDisk(t *testing.T) { ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { - Config: testAccComputeInstanceTemplate_withScratchDisk(RandString(t, 10)), + Config: testAccComputeInstanceTemplate_with375GbScratchDisk(RandString(t, 10)), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name_prefix"}, + }, + }, + }) +} + +func TestAccComputeInstanceTemplate_with18TbScratchDisk(t *testing.T) { + t.Parallel() + + VcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_with18TbScratchDisk(RandString(t, 10)), }, { ResourceName: "google_compute_instance_template.foobar", @@ -1977,7 +2016,7 @@ resource "google_compute_instance_template" "foobar" { `, suffix, suffix) } -func testAccComputeInstanceTemplate_withScratchDisk(suffix string) string { +func testAccComputeInstanceTemplate_with375GbScratchDisk(suffix string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { family = "centos-7" @@ -2005,6 +2044,70 @@ resource "google_compute_instance_template" "foobar" { `, suffix) } +func testAccComputeInstanceTemplate_with18TbScratchDisk(suffix string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "centos-7" + project = "centos-cloud" +} + +resource "google_compute_instance_template" "foobar" { + name = "tf-test-instance-template-%s" + machine_type = "n2-standard-16" + can_ip_forward = false + disk { + source_image = data.google_compute_image.my_image.name + auto_delete = true + boot = true + } + disk { + auto_delete = true + disk_size_gb = 3000 + type = "SCRATCH" + disk_type = "local-ssd" + interface = "NVME" + } + disk { + auto_delete = true + disk_size_gb = 3000 + type = "SCRATCH" + disk_type = "local-ssd" + interface = "NVME" + } + disk { + auto_delete = true + disk_size_gb = 3000 + type = "SCRATCH" + disk_type = "local-ssd" + interface = "NVME" + } + disk { + auto_delete = true + disk_size_gb = 3000 + type = "SCRATCH" + disk_type = "local-ssd" + interface = "NVME" + } + disk { + auto_delete = true + disk_size_gb = 3000 + type = "SCRATCH" + disk_type = "local-ssd" + interface = "NVME" + } + disk { + auto_delete = true + disk_size_gb = 3000 + type = "SCRATCH" + disk_type = "local-ssd" + interface = "NVME" + } + network_interface { + network = "default" + } +}`, suffix) +} + func testAccComputeInstanceTemplate_regionDisks(suffix string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/google/resource_compute_instance_test.go b/google/resource_compute_instance_test.go index 6f2bfc99f69..2b2e7aa3cdf 100644 --- a/google/resource_compute_instance_test.go +++ b/google/resource_compute_instance_test.go @@ -721,7 +721,7 @@ func TestAccComputeInstance_bootDisk_mode(t *testing.T) { }) } -func TestAccComputeInstance_scratchDisk(t *testing.T) { +func TestAccComputeInstance_with375GbScratchDisk(t *testing.T) { t.Parallel() var instance compute.Instance @@ -733,7 +733,7 @@ func TestAccComputeInstance_scratchDisk(t *testing.T) { CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComputeInstance_scratchDisk(instanceName), + Config: testAccComputeInstance_with375GbScratchDisk(instanceName), Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), @@ -745,6 +745,33 @@ func TestAccComputeInstance_scratchDisk(t *testing.T) { }) } +func TestAccComputeInstance_with18TbScratchDisk(t *testing.T) { + // Skip this test until the quota for the GitHub presubmit GCP project is increased + // to handle the size of the resource this test spins up. + t.Skip() + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_with18TbScratchDisk(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceScratchDisk(&instance, []string{"NVME", "NVME", "NVME", "NVME", "NVME", "NVME"}), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + func TestAccComputeInstance_forceNewAndChangeMetadata(t *testing.T) { t.Parallel() @@ -4389,7 +4416,7 @@ resource "google_compute_instance" "foobar" { `, instance, diskMode) } -func testAccComputeInstance_scratchDisk(instance string) string { +func testAccComputeInstance_with375GbScratchDisk(instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { family = "debian-11" @@ -4422,6 +4449,60 @@ resource "google_compute_instance" "foobar" { `, instance) } +func testAccComputeInstance_with18TbScratchDisk(instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "n2-standard-64" // must be a large n2 to be paired with 18Tb local-ssd + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + scratch_disk { + interface = "NVME" + size = 3000 + } + + scratch_disk { + interface = "NVME" + size = 3000 + } + + scratch_disk { + interface = "NVME" + size = 3000 + } + + scratch_disk { + interface = "NVME" + size = 3000 + } + + scratch_disk { + interface = "NVME" + size = 3000 + } + + scratch_disk { + interface = "NVME" + size = 3000 + } + + network_interface { + network = "default" + } +}`, instance) +} + func testAccComputeInstance_serviceAccount(instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" {