terraform and references in local-exec DESTROY provisioners

16.9k Views Asked by At

i am trying to manage database users along with the database for an azure instance, and this is surprisingly … impossible. I thought I found a way using a local-exec provider, but … well, apparently not. the code and the error message are below.

it boils down to terraform complaining that I reference non-static stuff from other resources, which I just … don’t. I only use static parameters, nothing else. what I don’t understand is that I can reference variables even in provider configs - but for destroy provisioners it’s too dynamic?

appreciate any help!

and on to the code … :

resource "azurerm_postgresql_database" "db" {
  server_name         = var.server_name
  resource_group_name = var.server_rg
  name                = var.db_name
  charset             = var.db_charset
  collation           = var.db_collation


  provisioner "local-exec" {
    command = "${path.module}/mgt-user.sh create '${var.server_fqdn}' '${var.server_admin_user}' '${var.db_name}' '${var.db_user_pass}'"
  }

  provisioner "local-exec" {
    when    = destroy
    command = "${path.module}/mgt-user.sh destroy '${var.server_fqdn}' '${var.server_admin_user}' '${var.db_name}' '${var.db_user_pass}'"
  }
}

now when I run terraform init i get this:

Error: Invalid reference from destroy provisioner

  on ../modules/dbs/pg-db-and-user/db_and_user.tf line 27, in resource "azurerm_postgresql_database" "db":
  27:     command = "echo ${path.module}/create_user.sh destroy '${var.server_fqdn}' '${var.server_admin_user}' '${var.db_name}' '${var.db_user_pass}'"

Destroy-time provisioners and their connection configurations may only
reference attributes of the related resource, via 'self', 'count.index', or
'each.key'.

References to other resources during the destroy phase can cause dependency
cycles and interact poorly with create_before_destroy.
1

There are 1 best solutions below

2
On

Update

The below answer doesn't work. One way of doing is with null_resource with local-exec & triggers. An example is like ::

resource "null_resource" "delete_venafi_cert" {

triggers = {
    venafi_url      = var.venafi_url
    cert_name       = var.cert_name
    venafi_scope    = var.venafi_delete_scope
    venafi_client   = var.venafi_client_id
    venafi_oath_url = var.venafi_oauth_url
  }

  provisioner "local-exec" {
    when       = destroy
    command    = "${path.module}/delete-venafi-certificate.sh ${self.triggers.venafi_url} ${self.triggers.cert_name} ${self.triggers.venafi_scope} ${self.triggers.venafi_client} ${self.triggers.venafi_oath_url}"
    on_failure = continue
  }
}

BELOW ONE DOESN'T WORK

The below snippet must work with a warning rather than throwing an error. The problem was because of path.module variable being used in tandem with destroy provisioner.

Terraform says this will be improved in further releases. Until then, you could pass working_dir pointing to path.module var.

resource "azurerm_postgresql_database" "db" {
  server_name         = var.server_name
  resource_group_name = var.server_rg
  name                = var.db_name
  charset             = var.db_charset
  collation           = var.db_collation


  provisioner "local-exec" {
    command = "${path.module}/mgt-user.sh create '${var.server_fqdn}' '${var.server_admin_user}' '${var.db_name}' '${var.db_user_pass}'"
  }

  provisioner "local-exec" {
    when    = destroy
    command = "./mgt-user.sh destroy '${var.server_fqdn}' '${var.server_admin_user}' '${var.db_name}' '${var.db_user_pass}'"
    working_dir = path.module
  }
}

For more details, you could refer to below links::