Tips and Tricks with Terraform's null_resource

Posted on May 17, 2022   ·   2 min read   ·   # comments   ·   #today-i-learned  #programming

Terraform’s null_resource resource can be useful when there aren’t any existing modules to satisfy your needs (with some caveats). Hashicorp’s documentation for it is a bit lacking, but fortunately there’s more information about the provisioners in their other docs here. After using these resources in a handful of places across our infrastructure deployments, I’ve developed a small collection of tips I picked up over the past few months that I thought I’d share.

Use timestamp() as a trigger when you need the resource to run on every deployment:

resource "null_resource" "always-run" {
triggers = {
timestamp = timestamp()
}

provisioner "local-exec" {
command = "echo foobar"
}
}


You can also supply multiple provisioner blocks, where one of them can be configured with when = destroy to specify the action to take when the resource will be destroyed. Dynamic values need to be accessed using self.triggers.* since Terraform isn’t able to resolve the values at runtime during resource destruction.

resource "null_resource" "include-cleanup" {
triggers = {
name   = var.name
region = var.region
}

# Executes on resource creation {
command = join(" ", [
"echo",
"create:",
"${self.triggers.name}", "${self.triggers.region}",
])
}

# Executes on resource destruction
provisioner "local-exec" {
when = destroy
command = join(" ", [
"echo",
"destroy:",
"${self.triggers.name}", "${self.triggers.region}",
])
}
}


The local-exec provisioner also allows for an environment field, which can be used to easily pass values into commands or scripts:

resource "null_resource" "environment-values" {
provisioner "local-exec" {
command = "./some-script.sh"
environment = {
ENVIRONMENT = ${var.environment} JSON_DATA = jsonencode({ "var1" =${var.name},
"var2" = ${var.region}, ... }) } } }  Aside from provisioning resources, null_resource can also be used for debugging values (which I stumbled upon from nexxai.dev): resource "null_resource" "terraform-debug" { provisioner "local-exec" { command = "echo$VARIABLE1 >> debug.txt; echo \$VARIABLE2 >> debug.txt"

environment = {
VARIABLE1 = jsonencode(var.your_variable_name)
VARIABLE2 = jsonencode(local.piece_of_data)
}
}
}