hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.

Home Page:https://www.terraform.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

templatestring function allow for_each

reasland opened this issue · comments

Terraform Version

1.9.0-beta1

Use Cases

I am importing template files via the data HTTP resource, I give a list of files to import in a variable then use a for_each to import multiple items specified in configuration

Attempted Solutions

data "http" "function_data" {
  for_each = var.functions

  method = "GET"
  url = "https://gitlab.com/api/v4/projects/${each.value.project_id}/repository/files/${each.value.function}/raw?ref=${each.value.ref}"

  request_headers = {
    PRIVATE-TOKEN = var.gitlab_token
  }
}

# function being added in terraform 1.9

resource "aws_cloudfront_function" "functions" {
  for_each                     = var.functions
  name                         = each.key
  runtime                      = each.value.runtime
  comment                      = contains(keys(each.value), "comment") ? each.value.comment : ""
  code                         = templatestring(data.http.function_data[each.key].response_body, each.value.values)
}

above errors with this Invalid value for "template" parameter: invalid template expression: must be a direct reference to a single string from elsewhere, containing valid Terraform template syntax.

when I hardcode the each.key the issue is resolved, so I believe the current implementation of templatestring does not allow variables in the template section

I am able to use the hashicorp/template_file resource to bypass this issue, but that provider is depricated

Proposal

Allow variables to be used in templatestring() function in the template segment

References

No response

Hi @reasland! Thanks for this feedback.

Here's a different way you could write this which I would expect to work with the function as currently implemented:

resource "aws_cloudfront_function" "functions" {
  for_each = data.http.function_data

  name    = each.key
  runtime = var.functions[each.key].runtime
  comment = try(var.functions[each.key].comment, "")
  code    = templatestring(each.value.response_body, var.functions[each.key].values)
}

The general idea I followed here was to pivot to declaring one function per data.http.function_data result, rather than one function per element of var.functions. That then makes the first templatestring argument only a simple static reference, without any dynamic steps, and therefore works with the current set of rules.

However, I'm also going to investigate what it would take to also carve out support for what you tried here, since what you tried is indeed a reasonable thing to write to allow selecting a template dynamically for each element of a collection.

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.