Learn about Spacelift's latest features and capabilities šŸš€šŸš€

Register for the Product Momentum Webinar Aug 6 ā†’

Terraform

How to Use Terraform Try & Can Functions [Examples]

How to Use Terraform Try

In this article, we will take a look at some useful built-in functions you should know about in Terraform, tryĀ andĀ can, introduced to Terraform from version 12.20. We will explain what they are, and what they are used for, as well as run through some examples to show their usage. We will then describe how they compare to the lookup function.

  1. What does try function do in Terraform?
  2. Terraform try limitations and best practices
  3. Using Terraform try – example
  4. Terraform try vs lookup
  5. What is Terraform can function?
  6. Using Terraform can – examples

What does try function do in Terraform?

Terraform try evaluates all of its argument expressions in turn and returns the result of the first one that does not produce any errors. The tryĀ function can only catch and handleĀ dynamicĀ errors resulting from access to data that isn’t known until runtime. TheĀ tryĀ function is intended only for concise testing of the presence of and types of object attributes. It can technically accept any sort of expression.

How to use Terraform try?

 

try(value, default)
  • value: The value to look up in the map.
  • default: The value to return if the key is not found in the map.

Example:

locals {
 jedi_map = {
   darth = "sith"
 }
 try1 = try(local.jedi_map.boba_fett, "jedi")
}

output "try1" {
 value = local.try1
}

The output of this code will be ā€œjediā€, as the expressionĀ local.map_var.boba_fettĀ has not been declared.

If the value of theĀ tryĀ function used to evaluate the condition does not exist, then it will error. In the below example,Ā local.nothing.hereĀ is not declared in my configuration, and so the condition produces an error. It will not catch errors relating to expressions that can be proven to be invalid for any input, such as a malformed resource reference.

try function terraform

Terraform try limitations and best practices

Let’s now take a look at some limitations and best practices for the Terraform try function:

  1. tryĀ should be used when you donā€™t know if the data will exist or how it is going to be formed.
  2. Hashicorp recommends to use the try function only in special local values whose expressions perform normalization. To make sure that the error handling is confined to a single location in the module and the rest of the module can just use straightforward references to the normalized structure and thus be more readable for future maintainers.
  3. AlthoughĀ trycan technically accept any sort of expression it is recommended to use it only with simple attribute references and type conversion functions.
  4. Always try to keep your code simple to promote readability. Overuse of tryĀ to suppress errors will lead to a configuration that is hard to understand and maintain.

Check out other Terraform best practices to improve your Terraform workflow.

Using Terraform try ā€” examples

In this example, we use theĀ try function to check if a map of Kubernetes namespaces exists, if not, then it uses the default.

 config = {
    namespaces = ["namespace_jedi", "namespace_sith"]

    (...)
  }

resource "kubernetes_namespace" "ns" {
  for_each = var.config.namespaces

  (...)

resource "kubernetes_namespace" "ns" {
  for_each = try(var.config.namespaces, ["namespace_jedi", "namespace_sith"])

  (...)

In the next example,Ā tryĀ is used to deal with situations where a value might be provided in two different forms, allowing us to normalize to the most general form.

The variable accepts any type and the tryĀ function then uses theĀ tostringĀ andĀ tolist expressions to try a conversion to a string or a list.

variable "jedi_list" {
  type = any
}

locals {
  example = try(
    [tostring(var.jedi_list)],
    tolist(var.jedi_list),
  )
}

In the last example, we show how multiple values can be tested using theĀ tryĀ function. A locals map is specified with a key value pair ofĀ luke = "jedi" ā€” we then test for two unspecified values, before the third one will be used as it exists. The code below outputs jediĀ .

locals {
  jedi = {
    luke = "jedi"
  }
}

output "try" {
  value = try(local.jedi.bar, local.jedi.baz, local.jedi.luke, "not_a_jedi")
}

Terraform try vs lookup

Terraform try is a more general form of the lookup function in Terraform. The lookup function is used to retrieve the value of a map element or list element.

Usage:

lookup(map, key, [default])
  • map: The map from which to look up the value.
  • key: The key to look up in the map.
  • defaultĀ (optional): The value to return if the key is not found in the map. If not specified and the key is not found,Ā nullĀ is returned.

Terraform lookup example:

variable "jedi_map" {
  type    = map(string)
  default = {
    luke  = "jedi",
    darth = "sith",
  }
}

output "result" {
  value = lookup(var.jedi_map, "luke", "sith")
}

In this example,Ā lookupĀ is used to retrieve the value associated with the key “luke” from the mapĀ var.jedi_map. If the key is not found, it returns the default value “sith”. In this case, it will be found and return ā€œjediā€.

See also Terraform try vs coalesce function.

What is Terraform can function?

The Terraform can function tries evaluating an expression and returns a boolean value indicating whether it succeeded.

How to use Terraform can?

Let’s look at an example.

> local.jedi
{
  "yoda" = "jedi"
}
> can(local.jedi.yoda)
true
> can(local.jedi.darth)
false

In this example, a local map is declared with the key of ā€œyodaā€ and the value of ā€œjediā€. The can function is used to test if the value exists, and returns true if it does, and false if it does not.

Similar to theĀ tryĀ function, if the value is not declared, then an error message will be produced:

terraform lookup vs try

Using Terraform can ā€” example

The example below shows how to use theĀ canĀ function in variable validation to ensure a timestamp is valid. The condition will fail if the second argument is not a valid timestamp, using theĀ formatdate function.

variable "timestamp" {
  type        = string

  validation {
    condition     = can(formatdate("", var.timestamp))
    error_message = "The timestamp is invalid."
  }
}

Key points

In summary Terraform try evaluates all of its argument expressions in turn and returns the result of the first one that does not produce any errors and canĀ evaluates the given expression and returns a boolean value indicating whether the expression produced a result without any errors.

We encourage you also to exploreĀ how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. If you want to learn more,Ā create a free account todayĀ orĀ book a demo with one of our engineers.

Note:Ā New versions of Terraform will be placed under the BUSL license, but everything created before version 1.5.x stays open-source.Ā OpenTofuĀ is an open-source version of Terraform that will expand on Terraformā€™s existing concepts and offerings. It is a viable alternative to HashiCorpā€™s Terraform, being forked from Terraform version 1.5.6.Ā OpenTofu retained all the features and functionalities that had made Terraform popular among developers while also introducing improvements and enhancements. OpenTofu works with your existing Terraform state file, so you wonā€™t have any issues when you are migrating to it.

Manage Terraform Better with Spacelift

Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.

Start free trial

The Practitionerā€™s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide