From 16d9dc3368ee2cc9ec8086f54713bf5c184096d0 Mon Sep 17 00:00:00 2001 From: Andrew Starr-Bochicchio Date: Thu, 4 Oct 2018 14:23:11 -0400 Subject: [PATCH] Ensure floating_ip_assignment works with create_before_destroy (Fixes: #147). --- ...rce_digitalocean_floating_ip_assignment.go | 25 ++++-- ...igitalocean_floating_ip_assignment_test.go | 90 ++++++++++++++++++- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/digitalocean/resource_digitalocean_floating_ip_assignment.go b/digitalocean/resource_digitalocean_floating_ip_assignment.go index f4b53fd3..4fe15ff2 100644 --- a/digitalocean/resource_digitalocean_floating_ip_assignment.go +++ b/digitalocean/resource_digitalocean_floating_ip_assignment.go @@ -86,17 +86,28 @@ func resourceDigitalOceanFloatingIpAssignmentDelete(d *schema.ResourceData, meta client := meta.(*godo.Client) ip_address := d.Get("ip_address").(string) + droplet_id := d.Get("droplet_id").(int) - log.Printf("[INFO] Unassigning the Floating IP from the Droplet") - action, _, err := client.FloatingIPActions.Unassign(context.Background(), ip_address) + log.Printf("[INFO] Reading the details of the FloatingIP %s", ip_address) + floatingIp, _, err := client.FloatingIPs.Get(context.Background(), ip_address) if err != nil { - return fmt.Errorf("Error unassigning FloatingIP (%s) from the droplet: %s", ip_address, err) + return fmt.Errorf("Error retrieving FloatingIP: %s", err) } - _, unassignedErr := waitForFloatingIPAssignmentReady(d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) - if unassignedErr != nil { - return fmt.Errorf( - "Error waiting for FloatingIP (%s) to be unassigned: %s", ip_address, unassignedErr) + if floatingIp.Droplet.ID == droplet_id { + log.Printf("[INFO] Unassigning the Floating IP from the Droplet") + action, _, err := client.FloatingIPActions.Unassign(context.Background(), ip_address) + if err != nil { + return fmt.Errorf("Error unassigning FloatingIP (%s) from the droplet: %s", ip_address, err) + } + + _, unassignedErr := waitForFloatingIPAssignmentReady(d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID) + if unassignedErr != nil { + return fmt.Errorf( + "Error waiting for FloatingIP (%s) to be unassigned: %s", ip_address, unassignedErr) + } + } else { + log.Printf("[INFO] Floating IP already unassigned, removing from state.") } d.SetId("") diff --git a/digitalocean/resource_digitalocean_floating_ip_assignment_test.go b/digitalocean/resource_digitalocean_floating_ip_assignment_test.go index 77d25245..d80db765 100644 --- a/digitalocean/resource_digitalocean_floating_ip_assignment_test.go +++ b/digitalocean/resource_digitalocean_floating_ip_assignment_test.go @@ -52,6 +52,36 @@ func TestAccDigitalOceanFloatingIPAssignment(t *testing.T) { }) } +func TestAccDigitalOceanFloatingIPAssignment_createBeforeDestroy(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFloatingIPDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckDigitalOceanFloatingIPAssignmentConfig_createBeforeDestroy, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanFloatingIPAttachmentExists("digitalocean_floating_ip_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_floating_ip_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + resource.TestMatchResourceAttr( + "digitalocean_floating_ip_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + { + Config: testAccCheckDigitalOceanFloatingIPAssignmentConfig_createBeforeDestroyReassign, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanFloatingIPAttachmentExists("digitalocean_floating_ip_assignment.foobar"), + resource.TestMatchResourceAttr( + "digitalocean_floating_ip_assignment.foobar", "id", regexp.MustCompile("[0-9.]+")), + resource.TestMatchResourceAttr( + "digitalocean_floating_ip_assignment.foobar", "droplet_id", regexp.MustCompile("[0-9]+")), + ), + }, + }, + }) +} + func testAccCheckDigitalOceanFloatingIPAttachmentExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -92,7 +122,7 @@ resource "digitalocean_floating_ip" "foobar" { resource "digitalocean_droplet" "foobar" { count = 2 name = "foobar-${count.index}" - size = "1gb" + size = "s-1vcpu-1gb" image = "centos-7-x64" region = "nyc3" ipv6 = true @@ -113,7 +143,7 @@ resource "digitalocean_floating_ip" "foobar" { resource "digitalocean_droplet" "foobar" { count = 2 name = "foobar-${count.index}" - size = "1gb" + size = "s-1vcpu-1gb" image = "centos-7-x64" region = "nyc3" ipv6 = true @@ -134,10 +164,64 @@ resource "digitalocean_floating_ip" "foobar" { resource "digitalocean_droplet" "foobar" { count = 2 name = "foobar-${count.index}" - size = "1gb" + size = "s-1vcpu-1gb" image = "centos-7-x64" region = "nyc3" ipv6 = true private_networking = true } ` + +var testAccCheckDigitalOceanFloatingIPAssignmentConfig_createBeforeDestroy = ` +resource "digitalocean_droplet" "foobar" { + image = "centos-7-x64" + name = "foobar" + region = "nyc3" + size = "s-1vcpu-1gb" + private_networking = false + + lifecycle { + create_before_destroy = true + } +} + +resource "digitalocean_floating_ip" "foobar" { + region = "nyc3" +} + +resource "digitalocean_floating_ip_assignment" "foobar" { + ip_address = "${digitalocean_floating_ip.foobar.id}" + droplet_id = "${digitalocean_droplet.foobar.id}" + + lifecycle { + create_before_destroy = true + } +} +` + +var testAccCheckDigitalOceanFloatingIPAssignmentConfig_createBeforeDestroyReassign = ` +resource "digitalocean_droplet" "foobar" { + image = "ubuntu-18-04-x64" + name = "foobar" + region = "nyc3" + size = "s-1vcpu-1gb" + private_networking = false + + lifecycle { + create_before_destroy = true + } +} + +resource "digitalocean_floating_ip" "foobar" { + region = "nyc3" +} + +resource "digitalocean_floating_ip_assignment" "foobar" { + ip_address = "${digitalocean_floating_ip.foobar.id}" + droplet_id = "${digitalocean_droplet.foobar.id}" + + lifecycle { + create_before_destroy = true + } +} +`