claranet / jinjaform

Terraform wrapper with Jinja2 templates
MIT License
35 stars 8 forks source link

Jinjaforming {{ var.array }} causes items in the array to be surrounded by single quotes which causes Terraform to fail #22

Closed japtain-cack closed 5 years ago

japtain-cack commented 5 years ago

I'm using an "{{ var.array }}" in my terraform. However, after running jinjaform it's converted to "[ 'foo', 'bar' ]", which is a string since it's surrounded by double quotes. I understand why this is happening, it's simply substituting the {{ }} and the result is the variable surrounded in double quotes. Removing the double quotes surrounding my array in the terraform file {{ var.array }} causes a syntax issue however.

I'm not sure if this is intended behavior or if I'm just doing it wrong. Using the default syntax of "${var.array}" does still work, but I like jinja's syntax better and to have uniformity, I'd like to use jinja if possible.

PS. Great tool, solved many of my Terraform issues.

raymondbutcher commented 5 years ago

Hi,

Thanks for trying the project, glad you're finding it useful!

Removing the double quotes surrounding my array in the terraform file {{ var.array }} causes a syntax issue however.

Do you mean it causes syntax issues in your editor / using terraform fmt? I imagine that doing this would work if you ran jinjaform plan:

module "test" {
  source = "./test"
  test = {{ var.array }}
}

Syntax checks in the editor is the main problem I have with Jinjaform at the moment. It is sometimes really hard, or impossible, to mix template code and Terraform code in a way that works with my editor's syntax highlighting and auto formatting on save.

I was considering using different characters for block_start_string, variable_start_string etc. from http://jinja.pocoo.org/docs/2.10/api/#jinja2.Environment but haven't come up with anything good. I need to think about it properly and consider lots of use cases.

Or perhaps we should have test.tf.j2 write to test.tf for cases where it's too hard, then editors/tools/people won't expect the file to be valid Terraform code.

japtain-cack commented 5 years ago

I don't believe it's related to my editor (vim). I've been experimenting a bit and I think I've found the underlying issue. It's not that omitting the surrounding double quotes from the "{{ var.array }}" causes a problem, jinjaform is working perfectly actually. it's that Terraform doesn't like single quotes surrounding strings inside the array.

main.tf (using zones as an example)

 21   project_id                    = "${var.project_id}"
 22   name                          = "${var.clusterName}-cluster${var.clusterNameSuffix}"
 23   regional                      = false
 24   region                        = "${var.region}"
 25   zones                         = {{ var.zones }}
 26   network                       = "${var.network}"
 27   subnetwork                    = "${var.subnetwork}"

**terraform.tfvars***

  1 # gke configs
  2 zones = ["us-central1-a"]

.jinjaform/main.tf (after running jinjaform plan)

 23   project_id                    = "${var.project_id}"
 24   name                          = "${var.clusterName}-cluster${var.clusterNameSuffix}"
 25   regional                      = false
 26   region                        = "${var.region}"
 27   zones                         = ['us-central1-a']
 28   network                       = "${var.network}"
 29   subnetwork                    = "${var.subnetwork}"

If I change the single quotes in zones = ['us-central1-a'] to double quotes in the .jinjaform/main.tf manually, then run terraform plan inside the .jinjaform directory, everything works fine.

Here is the error produced if I simply run jinjaform plan using the examples above:

[jinjaform] combine: terraform.tfvars
[jinjaform] render: config.tf
[jinjaform] render: data.tf
[jinjaform] render: main.tf
[jinjaform] render: outputs.tf
[jinjaform] render: variables.tf
[jinjaform] run: ln -fs "${JINJAFORM_PROJECT_ROOT}/creds" "${JINJAFORM_WORKSPACE}/creds"
[jinjaform] run: terraform

Error: Error parsing /home/nathan.snow/git/taos-gke-cluster/cluster/.jinjaform/main.tf: At 27:36: illegal char                                                                                             
raymondbutcher commented 5 years ago

Oh, right. I guess Jinja2 is calling repr(var.zones) or something along those lines, and Python tries to use single quotes for strings.

You could do:

zones = [
  {% for zone in var.zones %}
  "{{ zone }}",
  {% endfor %}
]

Or maybe this will work:

zones = {{ var.zones | tojson }}
japtain-cack commented 5 years ago

I'm actually doing the first example already. I'll have to give the tojson a shot. Thanks.

raymondbutcher commented 5 years ago

Hi @japtain-cack I'm closing this as I don't think there's anything that needs fixing/changing here. Feel free to reopen it if you disagree.