Terraform conditional operator and long string

I have a conditional in Terraform like this

message = each.value.env == "production" ? "<A very long message that has other each.value.<values>>" : "<Another very long message that has other each.value.<values>>"

Is there a way in the conditional to split the conditional since every time I try to do something like this I get a syntax error:
message = each.value.env == "production" ? << EOT "<A very long message that has other each.value.<values>>" "<Another line>" EOT : << EOT "<Another very long message that has other each.value.<values>>" EOT

Keeping them all on one line and editing them is really painful.

Hi @srinath,

You can wrap any expression over multiple lines by introducing some sort of brackets around it. In your case the parentheses ( ) seem like the best choice because they will only serve as grouping ant not change the meaning in any other way:

  message = (
    each.value.env == "production" ?
    "long message one" :
    "long message two"
  )

The parentheses here tell the Terraform language parser that any newlines within are insignificant, whereas by default – without any brackets – a newline would mark the end of the definition of the argument, as we can see with the newline that comes after the closing ).

You can additionally use the “heredoc” multi-line string syntax in there if you wish, though in that case I might recommend splitting the messages out into separate local values so that it’ll be easier to read the condition using those messages. For example:

locals {
  production_message = <<-EOT
    blah blah blah blah
  EOT
  non_production_message = <<-EOT
    blah blah blah blah
  EOT
}

resource "example" "example" {
  for_each = ...

  message = (
    each.value.env == "production" ?
    local.production_message :
    local.non_production_message
  )
}

(There’s no requirement that you split the “heredoc” templates into separate local values – you can write them inline if you wish – but I typically try to keep conditional expressions relatively “shallow” so that its easier for a reader to skim and understand the logic.)

There are some other options here too, aside from the conditional operator. Writing the example above made me consider this third approach which uses a map to specify messages on a per-environment basis, with a fallback to a default message:

locals {
  env_messages = {
    production = <<-EOT
      blah blah blah blah
    EOT
    "(default)" = <-EOT
      blah blah blah blah
    EOT
  }
}

resource "example" "example" {
  for_each = ...

  message = try(
    local.env_messages[each.value.env],
    local.env_messages["(default)"],
  )
}

(this uses try to specify a fallback expression to use if the lookup by environment fails, so that you don’t need to specify a separate message for each possible environment.)

Thank you so much @apparentlymart ! Let me try it out and reply back if it works.

@apparentlymart
I did try this format out,

locals {
  production_message = <<-EOT
    blah blah blah blah
  EOT
  non_production_message = <<-EOT
    blah blah blah blah
  EOT
}

however if I use ${each.value.env} or any other each value I get a syntax error with the message that each cannot be used in there which is understandable. Is there a way to include each.value in the message definitions in locals?