Mastercard / terraform-provider-restapi

A terraform provider to manage objects in a RESTful API
Other
808 stars 217 forks source link

Delete API not triggered on destroy #143

Closed emmaroberts-nbs closed 3 years ago

emmaroberts-nbs commented 3 years ago

Currently has an API that only supports create and delete. When running terraform destroy, terraform is not picking that the restapi_object needs to be destroyed so the state file is been updated to remove the state of the restapi_object, but the invocation of the delete endpoint is not hit.

I'm currently using the latest publish version on terrafrom registry from fmontezuma.

Terraform code looks like this:

providers.tf

terraform {
  required_providers {
   external = {
      source = "hashicorp/external"
    }
    restapi = {
      source = "fmontezuma/restapi"
    }
  }
  required_version = ">= 0.15"
}

provider "restapi" {
  uri = "http:"
  headers = {
    "Accept"       = "application/vnd.schemaregistry.v1+json, application/vnd.schemaregistry+json, application/json"
    "Content-Type" = "application/json"

  }
  write_returns_object  = true
  create_returns_object = true
}

main.tf

locals {
 folder_name = "/tmp/files"

}
data "local_file" "main_schema" {
  filename = "${local.folder_name}/${var.schema_file}"
}

data "external" "main_schema" {
  program = ["bash", "${path.module}/files/addRefsToPayload.sh"]
  query = {
    current_payload = jsonencode({ "schema" : data.local_file.main_schema.content, "schemaType" : "PROTOBUF", "references" : [] })
    file_name       = "${local.folder_name}/${var.schema_file}"
  }
}
resource "restapi_object" "main_schema" {
  for_each      = var.subjects
  path          = "${var.base_schema_subject_url}/${each.key}-value/versions/{id}"
  create_method = "POST"
  update_method = "POST"
  update_path   = "${var.base_schema_subject_url}/${each.key}-value/versions"
  create_path   = "${var.base_schema_subject_url}/${each.key}-value/versions"
  destroy_method = "DELETE"
  data          = data.external.main_schema.result.payload
  id_attribute  = "id"
}
variable "subjects" {
  type        = set(string)
  description = "Set of subject names that the schema should be assigned to"
  default = ["test"]
}
variable "base_schema_subject_url" {
  type        = string
  description = "URL for the subject. "
 default = "//localhost:8081/subjects"
}

variable "schema_file" {
  type = string
  default = "main_schema.proto"
}

Running this will terraform version 0.15.3

When running terraform destroy, the result is: Screenshot 2021-06-30 at 13 53 52

When during a get on the api in question, the created resource from the restapi_object still exists

emmaroberts-nbs commented 3 years ago

As part of this issue, if I keep running terraform apply, the restapi_object keeps wanting to be created even

Steps to replicate:

terraform apply
# Changes applied successfully
# Make no changes to the terraform 
terraform apply

Observed behaviour: Second run will want to create the same resource as the 1st run. This happens on every terraform apply.

Expected behaviour: Second run of terraform apply with no changes should come back with No changes

emmaroberts-nbs commented 3 years ago

So this issue might be done to dynamically generated payload.

When I try the following configuration:

provider "restapi" {
  uri = "http://${var.schema_registry_domain}"
  headers = {
    "Accept"       = "application/vnd.schemaregistry.v1+json, application/vnd.schemaregistry+json, application/json"
    "Content-Type" = "application/json"

  }
  write_returns_object  = true
  create_returns_object = true
}
resource "restapi_object" "mode" {
  provider = restapi
  path           = "/mode"
  create_method  = "PUT"
  create_path    = "/mode"
  update_path    = "/mode"
  destroy_method = "GET"
  destroy_path   = "/mode"
  read_path      = "/mode"
  data           = jsonencode({ "mode" : "READWRITE" })
  id_attribute   = "mode"
  debug          = true
}

terraform apply worked and on the second run it didn't detect any changes When running terraform destroy on this configuration, the api is triggered.

Any suggestions as to why this happening?

DRuggeri commented 3 years ago

Hey there, @emmaroberts-nbs - thanks for checking in!

Your summary helps a lot - and there's an explanation indeed! There is a function that Terraform itself will use to determine if an object exists. In your case, because the API does not offer a read method (usually GET), this HTTP request will always result in an error. This error is coaxed to a "nope, that does not exist" response to Terraform.

Therefore, when Terraform is calculating the plan to delete, it is detecting that this resource does not exist and does not plan to invoke the delete function.

I'm afraid that, given the limitations of the API you are working with, there is no clean way to avoid this situation.

Feel free to reopen the issue with more details if something might allow this to be done!