Terraform: B780FFEC-B661-4EB8-9236-A01737AD98B6 bug

Created on 13 Jul 2015  ยท  10Comments  ยท  Source: hashicorp/terraform

#resource
resource "template_file" "ansible_hosts_template" {
    filename = "ansible_hosts.tpl"
    vars {
        aws_weave = "${formatlist("%s:%d\n", aws_instance.weave.*.public_ip, 888)}"
    }
}

output "ansible_hosts" {
    value = "${template_file.ansible_hosts_template.rendered}"
}
#template
[aws_weave]
${aws_weave}

Result have unexpected prefix

#result
[aws_weave]
B780FFEC-B661-4EB8-9236-A01737AD98B652.16.214.17:888
B780FFEC-B661-4EB8-9236-A01737AD98B652.18.133.153:888
B780FFEC-B661-4EB8-9236-A01737AD98B652.18.84.26:888
B780FFEC-B661-4EB8-9236-A01737AD98B6
bug providetemplate

Most helpful comment

Hi @dcosson -

From Terraform's perspective the interpolation target in the JSON is just a simple string. We're still missing the error message, so you got the UUID instead of an error similar to the one I sketched out above.

In your context you're looking for:

  • Input String: foo,bar
  • Output String: "foo", "bar"

This can be achieved using formatlist to add the quotes and join to add the commas:

variable "input" {
  default = "foo,bar"
}

output "output" {
  value = "[ ${join(", ", formatlist("\\"%s\\"", split(",", var.input)))} ]"
}

Hope this helps! :grinning:

All 10 comments

hot fix is:

output "ansible_hosts" {
    value = "${replace(template_file.ansible_hosts_template.rendered, "B780FFEC-B661-4EB8-9236-A01737AD98B6", "")}"
}

I think the only fix here would be to have the template provider automatically join string lists, but what should the default delimeter be? Empty string? Space? Newline? Comma?

I believe another option which makes this join more explicit is:

#resource
resource "template_file" "ansible_hosts_template" {
    filename = "ansible_hosts.tpl"
    vars {
        aws_weave = "${formatlist("%s:%d", aws_instance.weave.*.public_ip, 888)}"
    }
}

output "ansible_hosts" {
    value = "${join("\n", template_file.ansible_hosts_template.rendered)}"
}

Thanks for the report - the UUID (which internally delimits lists) is making in into the template because we're missing a check.

This should be an error message something like this:

Errors:

template_file.ansible_hosts_template: [aws_weave] Cannot pass a list
  into a template variable. You can convert the list to a string with `join()`.

Tagging as a bug and we'll use this issue to track adding the check.

You can fix your config like this:

output "ansible_hosts" {
    value = "${join("", template_file.ansible_hosts_template.rendered)}"
}

I just ran into this trying to use variables in an IAM policy json string.

Basically, I'm passing a list of resources to use in a policy to a module. Since module variables don't support lists, I'm passing them in as a string with commas.

Simple example to reproduce, in a heredoc IAM policy json doc:

"Resource": ["${split(",", "foo,bar")}"]

Turns into:

"Resource": ["B780FFEC-B661-4EB8-9236-A01737AD98B6fooB780FFEC-B661-4EB8-9236-A01737AD98B6barB780FFEC-B661-4EB8-9236-A01737AD98B6"]

The simple version of the replace fix doesn't work because the first and last UUID's need to be stripped out and the middle out and the middle ones need to be replaced with something like ",".

I suppose I can try two levels of replace with a capturing regex in one of them.

Ok, so this does work as a workaround:

"Resource": ["${replace(replace(split(",", "foo,bar"), "/(^B780FFEC-B661-4EB8-9236-A01737AD98B6|B780FFEC-B661-4EB8-9236-A01737AD98B6$)/", ""), "B780FFEC-B661-4EB8-9236-A01737AD98B6", "\", \"")}"]

Becomes:

"Resource": ["foo", "bar"]

Hi @dcosson -

From Terraform's perspective the interpolation target in the JSON is just a simple string. We're still missing the error message, so you got the UUID instead of an error similar to the one I sketched out above.

In your context you're looking for:

  • Input String: foo,bar
  • Output String: "foo", "bar"

This can be achieved using formatlist to add the quotes and join to add the commas:

variable "input" {
  default = "foo,bar"
}

output "output" {
  value = "[ ${join(", ", formatlist("\\"%s\\"", split(",", var.input)))} ]"
}

Hope this helps! :grinning:

Oh awesome, that is a bit nicer. Thanks!

The terraform doc example to use formatlist:

Example: formatlist("instance %v has private ip %v", aws_instance.foo.*.id, aws_instance.foo.*.private_ip).

shows this behaviour too.

This has been fixed for a bit, forgot to close this issue.

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.

Was this page helpful?
0 / 5 - 0 ratings