Hi guys,
I was using a list of maps earlier, had that bug. Went to use a map only instead and see how it behaves, same bug. I'd guess this has to do with the way Terraform computes fields, or guess them from static data?
Could you think of a work-around? Thank you.
Terraform v0.11.2
vpc_peerings = {}
#vpc_peerings = {
# "name::0" = "n0",
# "owner::0" = "o0",
# "subnet::0" = "s0",
# "name::1" = "n1",
# "owner::1" = "o1",
# "subnet::1" = "s1",
}
variable "vpc_peerings" {
type = "map"
}
data "aws_availability_zones" "azs" {}
resource "null_resource" "peerings" {
count = "${length(var.vpc_peerings) / 3 * length(data.aws_availability_zones.azs.names)}"
triggers {
vpc_peerings = "${jsonencode(var.vpc_peerings)}"
}
provisioner "local-exec" {
command = "echo ${var.vpc_peerings["name::${count.index/3}"]}"
}
}
https://gist.github.com/Quentin-M/38f56705ffd6a25b3cbd5913abec5c4c
Error: null_resource.peerings: 1 error(s) occurred:
* null_resource.peerings: At column 24, line 1: map "var.vpc_peerings" does not have any elements so cannot determine type. in:
echo ${var.vpc_peerings["name::${count.index/3}"]}
Non-empty map: length(vpc_peerings) / 3 * length(data.aws_availability_zones.azs.names) null_resource are created.
Empty map: No null_resource are created, no crash occurs.
Another example:
variable "enabled" {
description = "Defines whether the module is enabled or not"
}
variable "ca" {
description = "Optional CA keypair from which all certificates should be generated ('cert', 'key', 'alg')"
type = "map"
}
resource "tls_private_key" "ca" {
count = "${var.enabled == true && length(var.ca) == 0 ? 1 : 0}"
algorithm = "RSA"
rsa_bits = "2048"
}
resource "tls_self_signed_cert" "ca" {
count = "${var.enabled == true && length(var.ca) == 0 ? 1 : 0}"
key_algorithm = "${tls_private_key.ca.algorithm}"
private_key_pem = "${tls_private_key.ca.private_key_pem}"
is_ca_certificate = true
validity_period_hours = 8760
subject {
common_name = "etcd"
organization = "etcd"
}
allowed_uses = [
"key_encipherment",
"digital_signature",
"cert_signing",
]
}
locals {
ca = {
"cert" = "${length(var.ca) == 0 ? tls_self_signed_cert.ca.*.cert_pem[0] : var.ca["cert"]}"
"key" = "${length(var.ca) == 0 ? tls_private_key.ca.*.private_key_pem[0] : var.ca["key"]}"
"alg" = "${length(var.ca) == 0 ? tls_private_key.ca.*.algorithm[0] : var.ca["alg"]}"
}
}
* module.etcd.module.tls.local.ca: local.ca: At column 59, line 1: list "tls_self_signed_cert.ca.*.cert_pem" does not have any elements so cannot determine type. in:
${length(var.ca) == 0 ? tls_self_signed_cert.ca.*.cert_pem[0] : var.ca["cert"]}
For the later case, changing the locals definition to the following solves the issue, so not bad. For the initial post, I have not yet found a workaround.
locals {
ca = {
"cert" = "${length(var.ca["key"]) == 0 ? join("", tls_self_signed_cert.ca.*.cert_pem) : var.ca["cert"]}"
"key" = "${length(var.ca["key"]) == 0 ? join("", tls_private_key.ca.*.private_key_pem) : var.ca["key"]}"
"alg" = "${length(var.ca["key"]) == 0 ? join("", tls_private_key.ca.*.algorithm) : var.ca["alg"]}"
}
}
I'm running into this as well.
I'm doing a lookup on a list variable in my scenario.
Found a workaround in this other issue: https://github.com/hashicorp/terraform/issues/9858
I don't think it will work for us because there are situations where we wrap around this list with modulus, we would be pulling the dummy value at some point unless we did something really, really ugly.
Probably will just end up not using terraform for this.
I think what's going on here is that Terraform is trying to check that var.vpc_peerings["name::${count.index/3}"] is an expression that'll return a string value (since it's being interpolated), but in the current version of Terraform list and map values don't carry element type information around with them and so the type checker must inspect the contents of the list to know the type.
If that is indeed the problem here then it'll be fixed in the next major release of Terraform, where we're changing the type system of the language so that the element type of a map is part of the map's type, like this:
# Not yet implemented, and details may change before release
variable "vpc_peerings" {
type = map(string) # The part in parentheses is the element type
}
data "aws_availability_zones" "azs" {}
resource "null_resource" "peerings" {
count = "${length(var.vpc_peerings) / 3 * length(data.aws_availability_zones.azs.names)}"
triggers {
vpc_peerings = "${jsonencode(var.vpc_peerings)}"
}
provisioner "local-exec" {
# Since the element type is specified above, we now know the result here
# is a string without inspecting the contents of this map.
command = "echo ${var.vpc_peerings["name::${count.index/3}"]}"
}
}
Once we're closer to release we'll try this out against a real build and see if there are any other adjustments we need to make to solve this.
Hi again!
I'm pleased to report that this does indeed seem to be fixed with the configuration language changes in the master branch. I verified with the v0.12.0-alpha1 prerelease build using the following configuration adapted from yours:
variable "vpc_peerings" {
type = map(string)
default = {}
}
provider "aws" {
region = "us-west-2"
}
data "aws_availability_zones" "azs" {}
resource "null_resource" "peerings" {
count = "${length(var.vpc_peerings) / 3 * length(data.aws_availability_zones.azs.names)}"
triggers = {
vpc_peerings = "${jsonencode(var.vpc_peerings)}"
}
provisioner "local-exec" {
command = "echo ${var.vpc_peerings["name::${count.index / 3}"]}"
}
}
With an empty map, this produced no plan as expected:
$ terraform apply
data.aws_availability_zones.azs: Refreshing state...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
This fix will be included in the forthcoming v0.12.0 release. Thanks for reporting this, and thanks for your patience while we did the configuration engine updates to make it work.
Wow thanks a lot~ The past few days have felt like christmas getting all those "Issue closed" emails from you guys.
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.