terraform icon indicating copy to clipboard operation
terraform copied to clipboard

Conditional expression cannot be in multiple lines

Open mcgitty opened this issue 2 years ago • 2 comments

Terraform Version

Terraform v1.2.7
on darwin_amd64

Terraform Configuration Files

locals {
  resource_name_prefix            = lower(replace(var.resource_name_prefix, " ", "-"))
  resource_name_prefix_title_case = replace(title(replace(replace(var.resource_name_prefix, "-", " "), "_", " ")), " ", "")

  eks_node_groups = {
    for current_node_group in var.node_groups : current_node_group["name"] => {
      name          = current_node_group["name"],
      iam_role_name = length(regexall(".*-${local.resource_name_prefix}-.*", current_node_group["name"])) > 0 ?
                      title(current_node_group["name"]) :
                      "${local.resource_name_prefix_title_case}_${title(current_node_group["name"])}",
      tags = var.tags
    }
  }
}

Debug Output

│ Error: Invalid expression │ │ on .terraform/modules/eks/locals.tf line 44, in locals: │ 44: iam_role_name = length(regexall(".-${local.resource_name_prefix}-.", current_node_group["name"])) > 0 ? │ 45: title(current_node_group["name"]) : │ │ Expected the start of an expression, but found an invalid expression token.

Expected Behavior

Allow long conditional expression be broken into multiple lines, at least when the line ends with the conditional expression token ? and :.

Other Terraform language components already handles multiple line, so the language parser should be expanded to handle multiple lines for conditional expression ?:

Actual Behavior

Produced "Error: Invalid expression".

Steps to Reproduce

terraform apply terraform destroy

Additional Context

No response

References

No response

mcgitty avatar Sep 21 '22 15:09 mcgitty

Hi @mcgitty! Thanks for raising this.

I believe in this case the problem is not that this is a conditional expression but rather that the expression is not inside any sort of brackets, and so the parser doesn't understand that you intend the following lines to be a continuation of the previous line rather than the start of a new argument.

You can make this work for conditional expressions and any other expression type by wrapping the expression in parentheses:

      iam_role_name = (
        length(regexall(".*-${local.resource_name_prefix}-.*", current_node_group["name"])) > 0 ?
        title(current_node_group["name"]) :
        "${local.resource_name_prefix_title_case}_${title(current_node_group["name"])}"
      )

The parser counts opening and closing brackets (which also includes [, {, quotes, and multi-line string delimiters) and will continue parsing an expression over multiple lines as long as there's at least one level of bracket open. I suspect this is why you've seen this work for other kinds of expression: several other expression types have brackets as an inherent part of their grammar, such as the parentheses on a function call or the braces that delimit this overall object constructor.

apparentlymart avatar Sep 21 '22 21:09 apparentlymart