Yann Stoneman
Yann Stoneman

Reputation: 1208

How to do a bash `for` loop in terraform termplatefile?

I'm trying to include a bash script in an AWS SSM Document, via the Terraform templatefile function. In the aws:runShellScript section of the SSM document, I have a Bash for loop with an @ sign that seems to be creating an error during terraform validate.

Version of terraform: 0.13.5

Inside main.tf file:

resource "aws_ssm_document" "magical_document" {
  name              = "magical_ssm_doc"
  document_type     = "Command"
  document_format   = "YAML"
  target_type       = "/AWS::EC2::Instance"
  content           = templatefile(
    "${path.module}/ssm-doc.yml",
    {
      Foo: var.foo
    }
  )
}

Inside my ssm-doc.yaml file, I loop through an array:

for i in "$\{arr[@]\}"; do
  if test -f "$i" ; then
    echo "[monitor://$i]" >> $f
    echo "disabled=0" >> $f
    echo "index=$INDEX" >> $f
  fi
done

Error:

Error: Error in function call

Call to function "templatefile" failed: ./ssm-doc.yml:1,18-19: Invalid character; This character is not used within the language., and 1 other diagnostic(s).

I tried escaping the @ symbol, like \@, but it didn't help. How do I

Upvotes: 1

Views: 1504

Answers (1)

Yann Stoneman
Yann Stoneman

Reputation: 1208

Although the error is pointing to the @ symbol as being the cause of the error, it's the ${ } that's causing the problem, because this is Terraform interpolation syntax, and it applies to templatefiles too. As the docs say:

The template syntax is the same as for string templates in the main Terraform language, including interpolation sequences delimited with ${ ... }.

And the way to escape interpolation syntax in Terraform is with a double dollar sign.

for i in "$${arr[@]}"; do
  if test -f "$i" ; then
    echo "[monitor://$i]" >> $f
    echo "disabled=0" >> $f
    echo "index=$INDEX" >> $f
  fi
done

The interpolation syntax is useful with templatefile if you're trying to pass in an argument, such as, in the question Foo. This argument could be accessed within the yaml file as ${Foo}.

By the way, although this article didn't give the answer to this exact issue, it helped me get a deeper appreciation for all the work Terraform is doing to handle different languages via the templatefile function. It had some cool tricks for doing replacements to escape for different scenarios.

Upvotes: 2

Related Questions