mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-25 01:00:16 -05:00
198 lines
6.1 KiB
Plaintext
198 lines
6.1 KiB
Plaintext
---
|
|
page_title: Conditional Expressions - Configuration Language
|
|
description: >-
|
|
Conditional expressions select one of two values. You can use them to define
|
|
defaults to replace invalid values.
|
|
---
|
|
|
|
# Conditional Expressions
|
|
|
|
A _conditional expression_ uses the value of a boolean expression to select one of
|
|
two values.
|
|
|
|
> **Hands-on:** Try the [Create Dynamic Expressions](https://learn.hashicorp.com/tutorials/terraform/expressions?in=terraform/configuration-language&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
|
|
|
|
## Syntax
|
|
|
|
The syntax of a conditional expression is as follows:
|
|
|
|
```hcl
|
|
condition ? true_val : false_val
|
|
```
|
|
|
|
If `condition` is `true` then the result is `true_val`. If `condition` is
|
|
`false` then the result is `false_val`.
|
|
|
|
A common use of conditional expressions is to define defaults to replace
|
|
invalid values:
|
|
|
|
```
|
|
var.a != "" ? var.a : "default-a"
|
|
```
|
|
|
|
If `var.a` is an empty string then the result is `"default-a"`, but otherwise
|
|
it is the actual value of `var.a`.
|
|
|
|
## Conditions
|
|
|
|
The condition can be any expression that resolves to a boolean value. This will
|
|
usually be an expression that uses the equality, comparison, or logical
|
|
operators.
|
|
|
|
The following language features are particularly useful when writing condition expressions.
|
|
|
|
### `contains` Function
|
|
|
|
Use the built-in function `contains` to test whether a given value is one of a set of predefined valid values.
|
|
|
|
```hcl
|
|
condition = contains(["STAGE", "PROD"], var.environment)
|
|
```
|
|
|
|
### Boolean Operators
|
|
|
|
Use the boolean operators `&&` (AND), `||` (OR), and `!` (NOT) to combine multiple conditions together.
|
|
|
|
```hcl
|
|
condition = var.name != "" && lower(var.name) == var.name
|
|
```
|
|
|
|
### `length` Function
|
|
|
|
Require a non-empty list or map by testing the collection's length.
|
|
|
|
```hcl
|
|
condition = length(var.items) != 0
|
|
```
|
|
This is a better approach than directly comparing with another collection using `==` or `!=`. This is because the comparison operators can only return `true` if both operands have exactly the same type, which is often ambiguous for empty collections.
|
|
|
|
### `for` Expressions
|
|
|
|
Use `for` expressions in conjunction with the functions `alltrue` and `anytrue` to test whether a condition holds for all or for any elements of a collection.
|
|
|
|
```hcl
|
|
condition = alltrue([
|
|
for v in var.instances : contains(["t2.micro", "m3.medium"], v.type)
|
|
])
|
|
```
|
|
|
|
### `can` Function
|
|
|
|
Use the `can` function to concisely use the validity of an expression as a condition. It returns `true` if its given expression evaluates successfully and `false` if it returns any error, so you can use various other functions that typically return errors as a part of your condition expressions.
|
|
|
|
For example, you can use `can` with `regex` to test if a string matches a particular pattern because `regex` returns an error when given a non-matching string.
|
|
|
|
```hcl
|
|
condition = can(regex("^[a-z]+$", var.name)
|
|
```
|
|
|
|
You can also use `can` with the type conversion functions to test whether a value is convertible to a type or type constraint.
|
|
|
|
```hcl
|
|
# This remote output value must have a value that can
|
|
# be used as a string, which includes strings themselves
|
|
# but also allows numbers and boolean values.
|
|
condition = can(tostring(data.terraform_remote_state.example.outputs["name"]))
|
|
```
|
|
|
|
```hcl
|
|
# This remote output value must be convertible to a list
|
|
# type of with element type.
|
|
condition = can(tolist(data.terraform_remote_state.example.outputs["items"]))
|
|
```
|
|
|
|
You can also use `can` with attribute access or index operators to test whether a collection or structural value has a particular element or index.
|
|
|
|
```hcl
|
|
# var.example must have an attribute named "foo"
|
|
condition = can(var.example.foo) ```
|
|
|
|
```hcl
|
|
# var.example must be a sequence with at least one element
|
|
condition = can(var.example[0])
|
|
# (although it would typically be clearer to write this as a
|
|
# test like length(var.example) > 0 to better represent the
|
|
# intent of the condition.)
|
|
```
|
|
|
|
### `self` Object
|
|
|
|
Use the `self` object in postcondition blocks to refer to attributes of the instance under evaluation.
|
|
|
|
```hcl
|
|
resource "aws_instance" "example" {
|
|
instance_type = "t2.micro"
|
|
ami = "ami-abc123"
|
|
|
|
lifecycle {
|
|
postcondition {
|
|
condition = self.instance_state == "running"
|
|
error_message = "EC2 instance must be running."
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### `each` and `count` Objects
|
|
|
|
In blocks where `for_each` or `count` are set, use `each` and `count` objects to refer to other resources that are expanded in a chain.
|
|
|
|
```hcl
|
|
variable "vpc_cidrs" {
|
|
type = set(string)
|
|
}
|
|
|
|
data "aws_vpc" "example" {
|
|
for_each = var.vpc_cidrs
|
|
|
|
filter {
|
|
name = "cidr"
|
|
values = [each.key]
|
|
}
|
|
}
|
|
|
|
resource "aws_internet_gateway" "example" {
|
|
for_each = aws_vpc.example
|
|
vpc_id = each.value.id
|
|
|
|
lifecycle {
|
|
precondition {
|
|
condition = aws_vpc.example[each.key].state == "available"
|
|
error_message = "VPC ${each.key} must be available."
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Result Types
|
|
|
|
The two result values may be of any type, but they must both
|
|
be of the _same_ type so that Terraform can determine what type the whole
|
|
conditional expression will return without knowing the condition value.
|
|
|
|
If the two result expressions don't produce the same type then Terraform will
|
|
attempt to find a type that they can both convert to, and make those
|
|
conversions automatically if so.
|
|
|
|
For example, the following expression is valid and will always return a string,
|
|
because in Terraform all numbers can convert automatically to a string using
|
|
decimal digits:
|
|
|
|
```hcl
|
|
var.example ? 12 : "hello"
|
|
```
|
|
|
|
Relying on this automatic conversion behavior can be confusing for those who
|
|
are not familiar with Terraform's conversion rules though, so we recommend
|
|
being explicit using type conversion functions in any situation where there may
|
|
be some uncertainty about the expected result type.
|
|
|
|
The following example is contrived because it would be easier to write the
|
|
constant `"12"` instead of the type conversion in this case, but shows how to
|
|
use [`tostring`](/language/functions/tostring) to explicitly convert a number to
|
|
a string.
|
|
|
|
```hcl
|
|
var.example ? tostring(12) : "hello"
|
|
```
|