From 4fcde09f826e05f3d2a70e000a9b5b054398ffd7 Mon Sep 17 00:00:00 2001 From: Dana Hoffman Date: Wed, 21 Mar 2018 15:54:34 -0700 Subject: [PATCH] protect against an instance getting deleted by an igm while the disk is being detached --- google/resource_compute_disk.go | 4 ++ google/resource_compute_disk_test.go | 94 +++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/google/resource_compute_disk.go b/google/resource_compute_disk.go index 07ac880ed95..78fa5f33df0 100644 --- a/google/resource_compute_disk.go +++ b/google/resource_compute_disk.go @@ -380,6 +380,10 @@ func resourceComputeDiskDelete(d *schema.ResourceData, meta interface{}) error { err = computeOperationWait(config.clientCompute, op, call.project, fmt.Sprintf("Detaching disk from %s/%s/%s", call.project, call.zone, call.instance)) if err != nil { + if opErr, ok := err.(ComputeOperationError); ok && len(opErr.Errors) == 1 && opErr.Errors[0].Code == "RESOURCE_NOT_FOUND" { + log.Printf("[WARN] instance %q was deleted while awaiting detach", call.instance) + continue + } return err } } diff --git a/google/resource_compute_disk_test.go b/google/resource_compute_disk_test.go index 98f5fa88f7f..dd00b144ab9 100644 --- a/google/resource_compute_disk_test.go +++ b/google/resource_compute_disk_test.go @@ -2,6 +2,7 @@ package google import ( "fmt" + "os" "regexp" "strconv" "testing" @@ -10,7 +11,6 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" "google.golang.org/api/compute/v1" - "os" ) func TestDiskImageDiffSuppress(t *testing.T) { @@ -372,6 +372,61 @@ func TestAccComputeDisk_deleteDetach(t *testing.T) { }) } +func TestAccComputeDisk_deleteDetachIGM(t *testing.T) { + t.Parallel() + + diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + diskName2 := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + mgrName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + var disk compute.Disk + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeDiskDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeDisk_deleteDetachIGM(diskName, mgrName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeDiskExists( + "google_compute_disk.foo", &disk), + ), + }, + // this needs to be a second step so we refresh and see the instance + // listed as attached to the disk; the instance is created after the + // disk. and the disk's properties aren't refreshed unless there's + // another step + resource.TestStep{ + Config: testAccComputeDisk_deleteDetachIGM(diskName, mgrName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeDiskExists( + "google_compute_disk.foo", &disk), + testAccCheckComputeDiskInstances( + "google_compute_disk.foo", &disk), + ), + }, + // Change the disk name to recreate the instances + resource.TestStep{ + Config: testAccComputeDisk_deleteDetachIGM(diskName2, mgrName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeDiskExists( + "google_compute_disk.foo", &disk), + ), + }, + // Add the extra step like before + resource.TestStep{ + Config: testAccComputeDisk_deleteDetachIGM(diskName2, mgrName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeDiskExists( + "google_compute_disk.foo", &disk), + testAccCheckComputeDiskInstances( + "google_compute_disk.foo", &disk), + ), + }, + }, + }) +} + func TestAccComputeDisk_computeDiskUserRegex(t *testing.T) { shouldPass := []string{ @@ -637,3 +692,40 @@ resource "google_compute_instance" "bar" { } }`, diskName, instanceName) } + +func testAccComputeDisk_deleteDetachIGM(diskName, mgrName string) string { + return fmt.Sprintf(` +resource "google_compute_disk" "foo" { + name = "%s" + image = "debian-8-jessie-v20170523" + size = 50 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_instance_template" "template" { + machine_type = "g1-small" + + disk { + boot = true + source = "${google_compute_disk.foo.name}" + auto_delete = false + } + + network_interface { + network = "default" + } + + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_instance_group_manager" "manager" { + name = "%s" + base_instance_name = "disk-igm" + instance_template = "${google_compute_instance_template.template.self_link}" + zone = "us-central1-a" + target_size = 1 +}`, diskName, mgrName) +}