hashicorp / terraform-provider-template

Terraform template provider
https://www.terraform.io/docs/providers/template/
Mozilla Public License 2.0
131 stars 89 forks source link

The new 2.0.0 doesn't parse %${var} core #54

Open phreddrick opened 5 years ago

phreddrick commented 5 years ago

The updated template_file data source incorrectly parses template files when you have the sequence %${var} in it. It looks like the % messes up the parser so that it doesn't interpret the ${var}, but I can't find any way to escape this. This is a breaking issue for me, as the % is required for correct sudo syntax.

Terraform Version

Terraform v0.11.11

Affected Resource(s)

Please list the resources as a list, for example:

If this issue appears to affect multiple resources, it may be an issue with Terraform's core, so please mention this.

Terraform Configuration Files

data "template_file" "sudoers" {
  template = "${file("${path.module}/tpls/sudoers.tpl")}"
  vars {
    metagroup = "mymetagroup"
  }
}

output "sudoers" {
  value = "${data.template_file.sudoers.rendered}"
}
# Give ${metagroup} sudo access
%${metagroup} ALL=(ALL:ALL) ALL

Expected Behavior

terraform apply
data.template_file.sudoers: Refreshing state...

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

Outputs:

sudoers = # Give mymetagroup sudo access
%mymetagroup ALL=(ALL:ALL) ALL

Actual Behavior

terraform apply
data.template_file.sudoers: Refreshing state...

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

Outputs:

sudoers = # Give mymetagroup sudo access
%${metagroup} ALL=(ALL:ALL) ALL

Steps to Reproduce

  1. mkdir -p testit/tpls
  2. put the hcl from above into testit.tf
  3. put the other data above into tpls/sudoers.tpl
  4. terraform apply
apparentlymart commented 5 years ago

Hi @phreddrick,

We'll investigate the weird issue here... it looks like the % is escaping the ${ in a similar way that $${ would work, as a side effect of the new 2.0.0 feature allowing %{...} sequences that can themselves be escaped as %%{...}. That is, I think the escape handling is incorrectly permitting mixtures of % and $ rather than requiring two consecutive identical characters.

In the mean time, if you do not wish to pin your provider version back to 1.0.0 I think you can work around this by including the percent sign in the expression somehow. For example:

${join("", ["%", metagroup])} ALL=(ALL:ALL) ALL
phreddrick commented 5 years ago

Thanks for the workaround. It didn't occur to me to use one of the builtin functions like that.

phreddrick commented 5 years ago

Turns out the work-around doesn't work for terraform 0.11.11. I get:

data.template_file.sudoers: Refreshing state...

Error: Error refreshing state: 1 error(s) occurred:

* data.template_file.sudoers: 1 error(s) occurred:

* data.template_file.sudoers: data.template_file.sudoers: failed to render : <template_file>:3,1-1: Invalid character; This character is not used within the language., and 1 other diagnostic(s)

when I use the example you gave above.

phreddrick commented 5 years ago

So the following workaround worked for me with both 1.0.0 and 2.0.0:

send in "%" as a variable called percent, then the template file looks like:

# Give ${metagroup} sudo access
${join("", list(percent, metagroup))} ALL=(ALL:ALL) ALL
apparentlymart commented 5 years ago

Sorry, yes, the workaround I suggested was intended for provider 2.0.0. Provider 1.0.0 shouldn't need a workaround at all because it doesn't yet have the %{...} control sequence syntax that led to this parser bug.

However, if you wish to write configuration that works for both, the list(...) function is a good way to do that, since it's supported as an alias of [ ... ] for backward-compatibility.

phreddrick commented 5 years ago

yeah, I have to support both plugin's at the moment. At any rate, the big surprise to me was that I couldn't have the literal string "%" in the join, I had to pass it in as a variable