terraform-provider-azapi icon indicating copy to clipboard operation
terraform-provider-azapi copied to clipboard

Add property to delete property when removed from update resource

Open grayzu opened this issue 2 years ago • 5 comments

Add a property that will allow users to delete the properties being managed by an azapi_update_resource when the resource is deleted.

Property Name

retain_body_values_on_destroy

Default Value

true

Use Case

In some scenarios, it would be valuable to remove a property that has been set using the update resource when it is no longer defined in the configuration or the resource is removed. For example, assigning a route table or NSG to a subnet. With the current implementation, once either of these is assigned, there is no way to unassign them.

Example

resource "azapi_update_resource" "rt_sub_assoc" {
  type        = "Microsoft.Network/virtualNetworks/subnets@2022-05-01"
  resource_id = azurerm_subnet.subnet.id
  retain_body_values_on_destroy = false
  
  body = jsonencode({
    properties = {
      routeTable = {
        id = azurerm_route_table.rt.id
      }
    }
  })
}

Deleting the above resource should remove routeTable from the subnet resulting in the route table becoming disconnected.

grayzu avatar Oct 14 '22 21:10 grayzu

Hi @grayzu ,

Thank you for taking time to report this issue.

However, this feature is hard to support, we don't have knowledge about how to restore the resource, because it depends on how the service designs it.

In your example, if we make a PUT request without the routeTable property, we can remove the configuration, however, in other cases, omitted properties might be ignored by backend then the properties stay unchanged.

Another scenario is that user might had configured the routeTable by other client tools, and user uses azapi_update_resource to overwrite it. In this case, we don't know how to restore to previous configuration.

With above reasons, we leave the problem to the users:

This resource is used to add or modify properties on an existing resource. When delete azapi_update_resource, no operation will be performed, and these properties will stay unchanged. If you want to restore the modified properties to some values, you must apply the restored properties before deleting.

ms-henglu avatar Oct 17 '22 05:10 ms-henglu

Hey @ms-henglu,

Thanks for the quick response. This issue is NOT about restoring the previous value, it is about enabling a common scenario gap that is not currently possible with AzAPI: User adds a property or properties to an existing resource and they want the option to have the properties removed from the payload when removed from Terraform. This will NOT be the default behavior due to the concerns that you have above. That being said, if a user needs to this functionality, this optional property will enable it. Note that the name of the property does not imply anything about previous values.

In my initial example, without this new features, how can a user remove the routeTable property using AzAPI? They cannot, which means that they will always get an error when they try to remove the subnet.

LMK your thoughts.

grayzu avatar Oct 17 '22 17:10 grayzu

@grayzu I concur with your comments above. @ms-henglu in @grayzu's example, we typically expect a terraform deployment to be authoritative for the configuration, so should have the option of removing properties we have added, such as the routeTable property on subnets in the example, not just adding and updating them. Is this possible now in some way?

kahawai-sre avatar Jun 16 '23 19:06 kahawai-sre

It is an very annoying issue for example if a property you have set with a resource action must be removed before another resource is destroyed. You could use a delete time provisioner, but that would mean that you would have to use azure cli or curl in order to delete the object, (or trigger another instance of terraform on a different folder applying the patch... even though cool cannot recommend) So it would even help, if there were something like destroy_method = "PATCH" and destroy_body = "some long json body"

or even as a block for my totally unrelated example of the implementation of a custom domain to a container app. ;)

resource "azapi_resource_action" "container_app_custom_domain" {
  type        = "Microsoft.App/containerApps@2023-05-02-preview"
  resource_id = azurerm_container_app.container_app.id
  method = "PATCH"
  body     = jsonencode({
    properties = {
      configuration = {
        ingress = {
          customDomains = [
            {
              name          = "my.custom.domain"
              bindingType   = "SniEnabled"
              certificateId = azapi_resource.container_app_cert.id
            }
          ]         
        }
      }
    }
  })
  
  on_destroy {
    method = "PATCH"
    body     = jsonencode({
      properties = {
          configuration = {
            ingress = {
              customDomains = []
            }
        }
      }
    })
  } 
}


AndreasMWalter avatar Nov 23 '23 10:11 AndreasMWalter