Search code examples
terraform

Can Terraform Destroy resources created using the "http data source" provider?


I have a terraform project for deploying a few VMs into Azure. Once the VMS are created successfully I'm wanting to automate the creation of DNS records. Additionally the application that runs on the VMs has APIs to POST configurations. I've successfully created my DNS records and POSTed configurations to the VMs using the http provider. However when I run a terraform destroy it obviously doesn't destroy them. I'm curious if there is a way when running terraform destroy to have these records and configurations deleted? Is there a way to manually add destroy steps in which I could just send more http requests to delete them?

Is there a better method to doing this that you would recommend?

Also I'll be going back and making all these fields sensitive variables with a .tfvars file. This is simply for testing right now.

DNS record example using Cloudns

data "http" "dns_record" {
  url = "https://api.cloudns.net/dns/add-record.json?auth-id=0000&auth-password=0000&domain-name=domain.com&record-type=A&host=testhost&record=123.123.123.123&ttl=1800"
}

VM API config example

data "http" "config" {
  url = "https://host.domain.com/api/configuration/endpoint"
  method = "POST"
  request_body = jsonencode({"name"="testfield", "field_type"="configuration"})

  # Optional request headers
  request_headers = {
    authorization = var.auth
  }
}

Solution

  • You should not use data-sources for operations that are having non-idempotent side effects or changing any external state. A data sources should only read information, because Terraform does not store them in the state. Therefore, there is no mechanism to destroy data sources, as there is nothing to destroy.

    Specific Provider

    In your case, there seem to be community providers for your DNS provider, e.g.: mangadex-pub/cloudns. This way you could manage your DNS entry via a resource, which will be supported by destroy.

    resource "cloudns_dns_record" "some-record" {
      # something.cloudns.net 600 in A 1.2.3.4
      name  = "something"
      zone  = "cloudns.net"
      type  = "A"
      value = "1.2.3.4"
      ttl   = "600"
    }
    

    null_resource with provisioners

    In cases where there is no Terraform provider for the API you want to consume, you can try using a null_resource with provisioners. Providers have some caveats, use with caution. To cite the Terraform docs:

    Use provisioners as a last resort. There are better alternatives for most situations.

    resource "null_resource" "my_resource_id" {
      provisioner "local-exec" {
        command = "... command that creates the actual resource"
      }
    
      provisioner "local-exec" {
        when    = destroy
        command = "... command that destroys the actual resource"
      }
    }