provider/openstack: Handle Deleted Resources in Floating IP Association (#14533)
This commit modifies the openstack_compute_floatingip_associate_v2 resource to handle cases where the floating IP or instance were deleted outside of Terraform.
This commit is contained in:
parent
ba7f1aec1e
commit
5842642643
|
@ -5,7 +5,10 @@ import (
|
|||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
||||
nfloatingips "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
|
@ -79,12 +82,67 @@ func resourceComputeFloatingIPAssociateV2Create(d *schema.ResourceData, meta int
|
|||
}
|
||||
|
||||
func resourceComputeFloatingIPAssociateV2Read(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
computeClient, err := config.computeV2Client(GetRegion(d))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack compute client: %s", err)
|
||||
}
|
||||
|
||||
// Obtain relevant info from parsing the ID
|
||||
floatingIP, instanceId, fixedIP, err := parseComputeFloatingIPAssociateId(d.Id())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now check and see whether the floating IP still exists.
|
||||
// First try to do this by querying the Network API.
|
||||
networkEnabled := true
|
||||
networkClient, err := config.networkingV2Client(GetRegion(d))
|
||||
if err != nil {
|
||||
networkEnabled = false
|
||||
}
|
||||
|
||||
var exists bool
|
||||
if networkEnabled {
|
||||
log.Printf("[DEBUG] Checking for Floating IP existence via Network API")
|
||||
exists, err = resourceComputeFloatingIPAssociateV2NetworkExists(networkClient, floatingIP)
|
||||
} else {
|
||||
log.Printf("[DEBUG] Checking for Floating IP existence via Compute API")
|
||||
exists, err = resourceComputeFloatingIPAssociateV2ComputeExists(computeClient, floatingIP)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
d.SetId("")
|
||||
}
|
||||
|
||||
// Next, see if the instance still exists
|
||||
instance, err := servers.Get(computeClient, instanceId).Extract()
|
||||
if err != nil {
|
||||
if CheckDeleted(d, err, "instance") == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, check and see if the floating ip is still associated with the instance.
|
||||
var associated bool
|
||||
for _, networkAddresses := range instance.Addresses {
|
||||
for _, element := range networkAddresses.([]interface{}) {
|
||||
address := element.(map[string]interface{})
|
||||
if address["OS-EXT-IPS:type"] == "floating" && address["addr"] == floatingIP {
|
||||
associated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !associated {
|
||||
d.SetId("")
|
||||
}
|
||||
|
||||
// Set the attributes pulled from the composed resource ID
|
||||
d.Set("floating_ip", floatingIP)
|
||||
d.Set("instance_id", instanceId)
|
||||
d.Set("fixed_ip", fixedIP)
|
||||
|
@ -128,3 +186,49 @@ func parseComputeFloatingIPAssociateId(id string) (string, string, string, error
|
|||
|
||||
return floatingIP, instanceId, fixedIP, nil
|
||||
}
|
||||
|
||||
func resourceComputeFloatingIPAssociateV2NetworkExists(networkClient *gophercloud.ServiceClient, floatingIP string) (bool, error) {
|
||||
listOpts := nfloatingips.ListOpts{
|
||||
FloatingIP: floatingIP,
|
||||
}
|
||||
allPages, err := nfloatingips.List(networkClient, listOpts).AllPages()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
allFips, err := nfloatingips.ExtractFloatingIPs(allPages)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(allFips) > 1 {
|
||||
return false, fmt.Errorf("There was a problem retrieving the floating IP")
|
||||
}
|
||||
|
||||
if len(allFips) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func resourceComputeFloatingIPAssociateV2ComputeExists(computeClient *gophercloud.ServiceClient, floatingIP string) (bool, error) {
|
||||
// If the Network API isn't available, fall back to the deprecated Compute API.
|
||||
allPages, err := floatingips.List(computeClient).AllPages()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
allFips, err := floatingips.ExtractFloatingIPs(allPages)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, f := range allFips {
|
||||
if f.IP == floatingIP {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue