This is an automated email from the ASF dual-hosted git repository.

sudo87 pushed a commit to branch fix-ipaddress-sourcenat-delete
in repository 
https://gitbox.apache.org/repos/asf/cloudstack-terraform-provider.git

commit 98695a5bd6be6095d59063f8deb916c8f8c13eca
Author: Manoj Kumar <[email protected]>
AuthorDate: Fri Aug 28 15:28:02 2026 +0530

    Fix cloudstack_ipaddress delete silently succeeding on source-NAT IPs
    
    resourceCloudStackIPAddressDelete skipped the disassociate call entirely
    when is_source_nat was true and returned nil, so Terraform reported the
    resource destroyed while CloudStack left the IP allocated. Always call
    DisassociateIpAddress and propagate whatever CloudStack returns instead
    of swallowing it, matching every other error path in this file.
    
    Verified against a live 4.23.0.0 lab: against an implemented network
    with a running virtual router, CloudStack now correctly rejects the
    destroy (error 530, IP still in use for source NAT) instead of Terraform
    falsely reporting success; against a network that was never implemented,
    the disassociate genuinely succeeds and is now reported accurately.
---
 cloudstack/resource_cloudstack_ipaddress.go | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/cloudstack/resource_cloudstack_ipaddress.go 
b/cloudstack/resource_cloudstack_ipaddress.go
index 1af251f..a0c4ea2 100644
--- a/cloudstack/resource_cloudstack_ipaddress.go
+++ b/cloudstack/resource_cloudstack_ipaddress.go
@@ -276,23 +276,21 @@ func resourceCloudStackIPAddressRead(d 
*schema.ResourceData, meta interface{}) e
 }
 
 func resourceCloudStackIPAddressDelete(d *schema.ResourceData, meta 
interface{}) error {
-       if !d.Get("is_source_nat").(bool) {
-               cs := meta.(*cloudstack.CloudStackClient)
-
-               // Create a new parameter struct
-               p := cs.Address.NewDisassociateIpAddressParams(d.Id())
-
-               // Disassociate the IP address
-               if _, err := cs.Address.DisassociateIpAddress(p); err != nil {
-                       // This is a very poor way to be told the ID does no 
longer exist :(
-                       if strings.Contains(err.Error(), fmt.Sprintf(
-                               "Invalid parameter id value=%s due to incorrect 
long value format, "+
-                                       "or entity does not exist", d.Id())) {
-                               return nil
-                       }
+       cs := meta.(*cloudstack.CloudStackClient)
 
-                       return fmt.Errorf("Error disassociating IP address %s: 
%s", d.Id(), err)
+       // Create a new parameter struct
+       p := cs.Address.NewDisassociateIpAddressParams(d.Id())
+
+       // Disassociate the IP address
+       if _, err := cs.Address.DisassociateIpAddress(p); err != nil {
+               // This is a very poor way to be told the ID does no longer 
exist :(
+               if strings.Contains(err.Error(), fmt.Sprintf(
+                       "Invalid parameter id value=%s due to incorrect long 
value format, "+
+                               "or entity does not exist", d.Id())) {
+                       return nil
                }
+
+               return fmt.Errorf("Error disassociating IP address %s: %s", 
d.Id(), err)
        }
 
        return nil

Reply via email to