SomeGuyOnAComputer
SomeGuyOnAComputer

Reputation: 6208

Using ternary in terraform to choose between 2 different lists

I have two different lists list_a and list_b and I want to choose between them based on a value local.server

I've tried this and it doesn't work

locals {
  server = "ubuntu"
  list_a = "${list("aaa")}"
  list_b = "${list("bbb")}"
  chosen = "${local.server == "ubuntu" ? local.list_a : local.list_b}"
}

output "chosen" {
  value = "${local.chosen}"
}
Error: Error asking for user input: 1 error(s) occurred:

* local.chosen: local.chosen: At column 3, line 1: conditional operator cannot be used with list values in:

${local.server == "ubuntu" ? local.list_a : local.list_b}

Upvotes: 3

Views: 10783

Answers (3)

grizmin
grizmin

Reputation: 151

There is a nice workaround for those still using terraform < 0.12.x:

You can use split to create a string from a list, evaluate ternary then join to make it a list again.

a = ["list", "values", "for ubuntu"]
b = ["list", "values", "for others"]

new_list = "${split(",", local.server == "ubuntu" ? join(",", local.a) : join(",", local.b))}"

Upvotes: 1

SomeGuyOnAComputer
SomeGuyOnAComputer

Reputation: 6208

Interpolation only seems to work on strings so if we make the ternary expression return a string by joining an often unused character i.e. |

delim  = "|"
chosen = "${local.server == "ubuntu" ?
         join(local.delim, local.list_a) :
         join(local.delim, local.list_b)}"

and then we can change the output to split on that same delimiter

output "chosen" {
  value = "${split(local.delim, local.chosen)}"
}
✗ terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

chosen = [
    aaa
]

Upvotes: 2

Martin Atkins
Martin Atkins

Reputation: 74249

In Terraform v0.11, the conditional operator works only with primitive-typed values (strings, numbers, booleans). You can work around this by constructing a map with the two options and then conditionally choosing a key, as opposed to conditionally choosing a value:

locals {
  lists = {
    a = "${list("aaa")}"
    b = "${list("bbb")}"
  }
}

output "chosen" {
  value = "${local.lists[local.server == "ubuntu" ? "a" : "b"]}"
}

In the forthcoming (at the time of writing) Terraform v0.12 release, the conditional operator works with values of any type, as long as both the true and false expressions can be converted to the same type during type checking, so your original example would work but can be rewritten using the first-class expression syntax also introduced by v0.12:

locals {
  server = "ubuntu"
  list_a = ["aaa"]
  list_b = ["bbb"]
  chosen = local.server == "ubuntu" ? local.list_a : local.list_b
}

output "chosen" {
  value = local.chosen
}

Upvotes: 7

Related Questions