terraform/website/docs/language/functions/one.html.md

122 lines
3.3 KiB
Markdown
Raw Normal View History

lang/funcs: "one" function In the Terraform language we typically use lists of zero or one values in some sense interchangably with single values that might be null, because various Terraform language constructs are designed to work with collections rather than with nullable values. In Terraform v0.12 we made the splat operator [*] have a "special power" of concisely converting from a possibly-null single value into a zero-or-one list as a way to make that common operation more concise. In a sense this "one" function is the opposite operation to that special power: it goes from a zero-or-one collection (list, set, or tuple) to a possibly-null single value. This is a concise alternative to the following clunky conditional expression, with the additional benefit that the following expression is also not viable for set values, and it also properly handles the case where there's unexpectedly more than one value: length(var.foo) != 0 ? var.foo[0] : null Instead, we can write: one(var.foo) As with the splat operator, this is a tricky tradeoff because it could be argued that it's not something that'd be immediately intuitive to someone unfamiliar with Terraform. However, I think that's justified given how often zero-or-one collections arise in typical Terraform configurations. Unlike the splat operator, it should at least be easier to search for its name and find its documentation the first time you see it in a configuration. My expectation that this will become a common pattern is also my justification for giving it a short, concise name. Arguably it could be better named something like "oneornull", but that's a pretty clunky name and I'm not convinced it really adds any clarity for someone who isn't already familiar with it.
2021-01-09 01:02:56 +01:00
---
layout: "language"
page_title: "one - Functions - Configuration Language"
sidebar_current: "docs-funcs-collection-one"
description: |-
The 'one' function transforms a list with either zero or one elements into
either a null value or the value of the first element.
---
# `one` Function
-> **Note:** This function is available only in Terraform v0.15 and later.
`one` takes a list, set, or tuple value with either zero or one elements.
If the collection is empty, `one` returns `null`. Otherwise, `one` returns
the first element. If there are two or more elements then `one` will return
an error.
This is a specialized function intended for the common situation where a
conditional item is represented as either a zero- or one-element list, where
a module author wishes to return a single value that might be null instead.
For example:
```hcl
variable "include_ec2_instance" {
type = bool
default = true
}
resource "aws_instance" "example" {
count = var.include_ec2_instance ? 1 : 0
# (other resource arguments...)
}
output "instance_ip_address" {
value = one(aws_instance.example[*].private_ip)
}
```
Because the `aws_instance` resource above has the `count` argument set to a
conditional that returns either zero or one, the value of
`aws_instance.example` is a list of either zero or one elements. The
`instance_ip_address` output value uses the `one` function as a concise way
to return either the private IP address of a single instance, or `null` if
no instances were created.
## Relationship to the "Splat" Operator
The Terraform language has a built-in operator `[*]`, known as
2021-06-09 12:13:08 +02:00
[the _splat_ operator](../expressions/splat.html), and one of its functions
lang/funcs: "one" function In the Terraform language we typically use lists of zero or one values in some sense interchangably with single values that might be null, because various Terraform language constructs are designed to work with collections rather than with nullable values. In Terraform v0.12 we made the splat operator [*] have a "special power" of concisely converting from a possibly-null single value into a zero-or-one list as a way to make that common operation more concise. In a sense this "one" function is the opposite operation to that special power: it goes from a zero-or-one collection (list, set, or tuple) to a possibly-null single value. This is a concise alternative to the following clunky conditional expression, with the additional benefit that the following expression is also not viable for set values, and it also properly handles the case where there's unexpectedly more than one value: length(var.foo) != 0 ? var.foo[0] : null Instead, we can write: one(var.foo) As with the splat operator, this is a tricky tradeoff because it could be argued that it's not something that'd be immediately intuitive to someone unfamiliar with Terraform. However, I think that's justified given how often zero-or-one collections arise in typical Terraform configurations. Unlike the splat operator, it should at least be easier to search for its name and find its documentation the first time you see it in a configuration. My expectation that this will become a common pattern is also my justification for giving it a short, concise name. Arguably it could be better named something like "oneornull", but that's a pretty clunky name and I'm not convinced it really adds any clarity for someone who isn't already familiar with it.
2021-01-09 01:02:56 +01:00
is to translate a primitive value that might be null into a list of either
zero or one elements:
```hcl
variable "ec2_instance_type" {
description = "The type of instance to create. If set to null, no instance will be created."
type = string
default = null
}
resource "aws_instance" "example" {
count = length(var.ec2_instance_type[*])
instance_type = var.ec2_instance_type
# (other resource arguments...)
}
output "instance_ip_address" {
value = one(aws_instance.example[*].private_ip)
}
```
In this case we can see that the `one` function is, in a sense, the opposite
of applying `[*]` to a primitive-typed value. Splat can convert a possibly-null
value into a zero-or-one list, and `one` can reverse that to return to a
primitive value that might be null.
## Examples
```
> one([])
null
> one(["hello"])
"hello"
> one(["hello", "goodbye"])
Error: Invalid function argument
Invalid value for "list" parameter: must be a list, set, or tuple value with
either zero or one elements.
```
### Using `one` with sets
The `one` function can be particularly helpful in situations where you have a
set that you know has only zero or one elements. Set values don't support
indexing, so it's not valid to write `var.set[0]` to extract the "first"
element of a set, but if you know that there's only one item then `one` can
isolate and return that single item:
```
> one(toset([]))
null
> one(toset(["hello"]))
"hello"
```
Don't use `one` with sets that might have more than one element. This function
will fail in that case:
```
> one(toset(["hello","goodbye"]))
Error: Invalid function argument
Invalid value for "list" parameter: must be a list, set, or tuple value with
either zero or one elements.
```