silent
silent

Reputation: 16208

Create resource via terraform but do not recreate if manually deleted?

I want to initially create a resource using Terraform, but if the resource gets later deleted outside of TF - e.g. manually by a user - I do not want terraform to re-create it. Is this possible?

In my case the resource is a blob on an Azure Blob storage. I tried using ignore_changes = all but that didn't help. Every time I ran terraform apply, it would recreate the blob.

resource "azurerm_storage_blob" "test" {
  name                   = "myfile.txt"
  storage_account_name   = azurerm_storage_account.deployment.name
  storage_container_name = azurerm_storage_container.deployment.name
  type                   = "Block"
  source_content         = "test"

  lifecycle {
    ignore_changes = all
  }
}

Upvotes: 0

Views: 3494

Answers (2)

Martin Atkins
Martin Atkins

Reputation: 74694

The requirement you've stated is not supported by Terraform directly. To achieve it you will need to either implement something completely outside of Terraform or use Terraform as part of some custom scripting written by you to perform a few separate Terraform steps.

If you want to implement it by wrapping Terraform then I will describe one possible way to do it, although there are various other variants of this that would get a similar effect.

My idea for implementing it would be to implement a sort of "bootstrapping mode" which your custom script can enable only for initial creation, but then for subsequent work you would not use the bootstrapping mode. Bootstrapping mode would be a combination of an input variable to activate it and an extra step after using it.

variable "bootstrap" {
  type        = bool
  default     = false
  description = "Do not use this directly. Only for use by the bootstrap script."
}

resource "azurerm_storage_blob" "test" {
  count = var.bootstrap ? 1 : 0

  name                   = "myfile.txt"
  storage_account_name   = azurerm_storage_account.deployment.name
  storage_container_name = azurerm_storage_container.deployment.name
  type                   = "Block"
  source_content         = "test"
}

This alone would not be sufficient because normally if you were to run Terraform once with -var="bootstrap=true" and then again without it Terraform would plan to destroy the blob, after noticing it's no longer present in the configuration.

So to make this work we need a special bootstrap script which wraps Terraform like this:

terraform apply -var="bootstrap=true"
terraform state rm azurerm_storage_blob.test

That second terraform state rm command above tells Terraform to forget about the object it currently has bound to azurerm_storage_blob.test. That means that the object will continue to exist but Terraform will have no record of it, and so will behave as if it doesn't exist.

If you run the bootstrap script then, you will have the blob existing but with Terraform unaware of it. You can therefore then run terraform apply as normal (without setting the bootstrap variable) and Terraform will both ignore the object previously created and not plan to create a new one, because it will now have count = 0.

This is not a typical use-case for Terraform, so I would recommend to consider other possible solutions to meet your use-case, but I hope the above is useful as part of that design work.

Upvotes: 1

BeeDeeBePope
BeeDeeBePope

Reputation: 129

If you have a resource defined in terraform configuration then terraform will always try to create it. I can't imagine what is your setup, but maybe you want to take the blob creation to a CLI script and run terraform and the script in desired order.

Upvotes: 0

Related Questions