-2

There is one resource which don't have pre-defined resource. So as as workaround, we preferred to used "null-resource".

Let's discuss with a example (Please don't stick with this example. Try to get the nature of requirement. Played a lot with conditional expression) -

Based on the terraform ACTION value (apply, destroy etc), do the below activity. Enlighten here if more inbuilt Terraform environment variables are available that can provide more flexibility in automation.

locals {
  action = "${TF_CLI_ARGS}" == "apply" ? "install" : ("${TF_CLI_ARGS}" == "destroy" ? "remove" : "update")
  package = "httpd"
  version = "2.4.6"
}

resource "null_resource" "test" {
  triggers = {
    action = "${local.action}"
  }

  triggers = {
    action = "${local.version}"
  }

  provisioner "local-exec" {
    command = "yum -y ${local.action} ${package}-${version}"
  }
}

Case 1: Install

Install the given package if apply is in command line.

Case 2: Delete

Uninstall the given package if destroy is in command line.

Case 3: Update

Update the given package based on delta in version number.

Ashish Kumar
  • 524
  • 6
  • 18
  • Nice blog about conditonal logic https://blog.boltops.com/2020/10/03/terraform-hcl-conditional-logic/ – Richard Rublev Mar 11 '23 at 16:08
  • @RichardRublev Thanks but don't want to play with 2 level of activity. Logically think just to uninstall a package, firstly we have update the 'variable "create" to false' then apply it and then again do terraform destroy to delete the "null-resource". Core requirement is somehow to get current terraform action as varirable. – Ashish Kumar Mar 11 '23 at 16:23
  • By what you are saying `"Please don't stick with this example."` I get a feeling that what you are doing is not about installing packages with yum locally ... You start with `There is one resource which don't have pre-defined resource.` what resource is that? what terraform provider? ... Most terraform providers are Open Source, ideally you can make the changes there – Helder Sepulveda Mar 12 '23 at 01:52

1 Answers1

1

Terraform is a desired state system, so the configuration describes the system that ought to exist rather than the specific actions required to create it.

When you create a destroy-mode plan Terraform still checks that the configuration is valid but ignores most of it because destroying is primarily a state-driven operation: any object that is tracked in the state must be planned for destruction regardless of how it is configured.

However, in your particular case you are using Provisioners, which are essentially an escape hatch to tell Terraform to perform imperative actions during either the create or destroy actions of instances of a particular resource. This is a pragmatic exception to the "desired state" structure which is defining a specific action to take rather than just a declaration of what ought to exist.

Due to provisioners being an imperative escape hatch, they do have the ability to react to create vs. destroy, like this:

  provisioner "local-exec" {
    # create-time provisioner
  }

  provisioner "local-exec" {
    when = destroy
    # destroy-time provisioner
  }

With blocks like the above in any resource block, Terraform will execute the create-time provisioner as part of applying any "create" action for an instance of the resource, and the destroy-time provisioner as part of applying a "destroy" action for an instance of the resource. Terraform will sometimes plan to replace an object with a new equivalent object, in which case that counts as both a create and a destroy action and so both would run when applying that change.

Provisioners are a last resort, so better to use a declarative mechanism included as part of a provider if possible, but if there's no way to achieve your goal other than provisioners then using this pairing of create-time and destroy-time provisioners is one way to make the imperative actions behave in a "resource-like" way.

Martin Atkins
  • 62,420
  • 8
  • 120
  • 138