diff --git a/configs/configupgrade/test-fixtures/valid/resource-count-ref/input/resource-count-ref.tf b/configs/configupgrade/test-fixtures/valid/resource-count-ref/input/resource-count-ref.tf new file mode 100644 index 0000000000..6b4647c3b3 --- /dev/null +++ b/configs/configupgrade/test-fixtures/valid/resource-count-ref/input/resource-count-ref.tf @@ -0,0 +1,29 @@ +resource "test_instance" "one" { +} + +resource "test_instance" "many" { + count = 2 +} + +data "terraform_remote_state" "one" { +} + +data "terraform_remote_state" "many" { + count = 2 +} + +output "managed_one" { + value = "${test_instance.one.count}" +} + +output "managed_many" { + value = "${test_instance.many.count}" +} + +output "data_one" { + value = "${data.terraform_remote_state.one.count}" +} + +output "data_many" { + value = "${data.terraform_remote_state.many.count}" +} diff --git a/configs/configupgrade/test-fixtures/valid/resource-count-ref/want/resource-count-ref.tf b/configs/configupgrade/test-fixtures/valid/resource-count-ref/want/resource-count-ref.tf new file mode 100644 index 0000000000..a20b45d88c --- /dev/null +++ b/configs/configupgrade/test-fixtures/valid/resource-count-ref/want/resource-count-ref.tf @@ -0,0 +1,29 @@ +resource "test_instance" "one" { +} + +resource "test_instance" "many" { + count = 2 +} + +data "terraform_remote_state" "one" { +} + +data "terraform_remote_state" "many" { + count = 2 +} + +output "managed_one" { + value = 1 +} + +output "managed_many" { + value = length(test_instance.many) +} + +output "data_one" { + value = 1 +} + +output "data_many" { + value = length(data.terraform_remote_state.many) +} diff --git a/configs/configupgrade/test-fixtures/valid/resource-count-ref/want/versions.tf b/configs/configupgrade/test-fixtures/valid/resource-count-ref/want/versions.tf new file mode 100644 index 0000000000..d9b6f790b9 --- /dev/null +++ b/configs/configupgrade/test-fixtures/valid/resource-count-ref/want/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 0.12" +} diff --git a/configs/configupgrade/upgrade_expr.go b/configs/configupgrade/upgrade_expr.go index de4480af40..8ff8bb51c5 100644 --- a/configs/configupgrade/upgrade_expr.go +++ b/configs/configupgrade/upgrade_expr.go @@ -224,6 +224,44 @@ Value: // here so we can normalize and introduce some newer syntax where it's // safe to do so. parts := strings.Split(tv.Name, ".") + + // First we need to deal with the .count pseudo-attributes that 0.11 and + // prior allowed for resources. These no longer exist, because they + // don't do anything we can't do with the length(...) function. + if len(parts) > 0 { + var rAddr addrs.Resource + switch parts[0] { + case "data": + if len(parts) == 4 && parts[3] == "count" { + rAddr.Mode = addrs.DataResourceMode + rAddr.Type = parts[1] + rAddr.Name = parts[2] + } + default: + if len(parts) == 3 && parts[2] == "count" { + rAddr.Mode = addrs.ManagedResourceMode + rAddr.Type = parts[0] + rAddr.Name = parts[1] + } + } + + // We need to check if the thing being referenced is actually an + // existing resource, because other three-part traversals might + // coincidentally end with "count". + if hasCount, exists := an.ResourceHasCount[rAddr]; exists { + if hasCount { + buf.WriteString("length(") + buf.WriteString(rAddr.String()) + buf.WriteString(")") + } else { + // If the resource does not have count, the .count + // attr would've always returned 1 before. + buf.WriteString("1") + } + break Value + } + } + parts = upgradeTraversalParts(parts, an) // might add/remove/change parts first, remain := parts[0], parts[1:] buf.WriteString(first)