Terraform: Parsing of maps in JSON variable files is broken.

Created on 13 Jul 2017  ยท  5Comments  ยท  Source: hashicorp/terraform

When declaring a map in JSON format in a Terraform variable file, it produces the error:

invalid value "myfile.tfvars" for flag -var-file: multiple map declarations not supported for variables

This looks to be a specific issue for the JSON format. Maps appear to work correctly for the HCL format, but is broken when using JSON.

Terraform Version

Terraform 0.9.11

Terraform Configuration Files

main.tf

variable "test_map" {
    type = "map"
}

hcl.tfvars

test_map = {
    "key1" = {
        "index1" = "data2"
        "index2" = "data2"
    }
    "key2" = {
        "index1" = "data1"
    }
}

json.tfvars

{ "test_map": { "key1": {"index1": "data1", "index2": "data2"}, "key2": {"index1": "data1"} } }

Debug Output

https://gist.github.com/dbeckham/6a85d7c0fdbaed19521ff59ffb12b387

Expected Behavior

The JSON format should be treated exactly the same as HCL, and both test HCL and JSON test files should be treated the same.

Actual Behavior

Terraform produced the error:

invalid value "myfile.tfvars" for flag -var-file: multiple map declarations not supported for variables

Steps to Reproduce

Take the three files above and run the following commands:

If you run Terraform using the HCL file agove, you get the normal output telling you:

$ terraform plan -var-file=hcl.tfvars
No changes. Infrastructure is up-to-date.

If you run the same command using the JSON version, you get the error:

$ terraform plan -var-file=json.tfvars
invalid value "json.tfvars" for flag -var-file: multiple map declarations not supported for variables
bug config

Most helpful comment

As far as I can tell this is a more widespread bug regarding maps in JSON files. While the documentation claims that JSON and HCL are interchangeable, as far as maps are concerned, this appears to not be the case.

My use case is managing Amazon ECR (docker image for ECS) repositories. You need to define an ECR Repository for _every_ image, so this becomes really cumbersome to maintain manually... so I'm trying to generate the terraform config from an external datasource.

I'm seeing this same bug, but with a map in an output in a .tf.json file.

infra_ecr.tf.json:

{
  "resource": {
    "aws_ecr_repository": {
      "jantman_private-docker-redirector": {
        "name": "jantman/private-docker-redirector"
      }
    }
  },
  "output": {
    "ecr_jantman_private-docker-redirector": {
      "value": {
        "arn": "${aws_ecr_repository.jantman_private-docker-redirector.arn}",
        "name": "${aws_ecr_repository.jantman_private-docker-redirector.name}",
        "registry_id": "${aws_ecr_repository.jantman_private-docker-redirector.registry_id}",
        "url": "${aws_ecr_repository.jantman_private-docker-redirector.url}"
      }
    }
  }
}

fails with:

* ecr_jantman_private-docker-redirector: output has invalid keys: registry_id, url, arn, name
* ecr_jantman_private-docker-redirector: output is missing required 'value' key

But infra_ecr.tf:

resource "aws_ecr_repository" "jantman_private-docker-redirector" {
  name = "jantman/private-docker-redirector"
}

output "ecr_jantman_private-docker-redirector" {
  value = {
    "arn" = "${aws_ecr_repository.jantman_private-docker-redirector.arn}",
    "name" = "${aws_ecr_repository.jantman_private-docker-redirector.name}",
    "registry_id" = "${aws_ecr_repository.jantman_private-docker-redirector.registry_id}",
    "url" = "${aws_ecr_repository.jantman_private-docker-redirector.url}"
  }
}

works fine.

All 5 comments

As far as I can tell this is a more widespread bug regarding maps in JSON files. While the documentation claims that JSON and HCL are interchangeable, as far as maps are concerned, this appears to not be the case.

My use case is managing Amazon ECR (docker image for ECS) repositories. You need to define an ECR Repository for _every_ image, so this becomes really cumbersome to maintain manually... so I'm trying to generate the terraform config from an external datasource.

I'm seeing this same bug, but with a map in an output in a .tf.json file.

infra_ecr.tf.json:

{
  "resource": {
    "aws_ecr_repository": {
      "jantman_private-docker-redirector": {
        "name": "jantman/private-docker-redirector"
      }
    }
  },
  "output": {
    "ecr_jantman_private-docker-redirector": {
      "value": {
        "arn": "${aws_ecr_repository.jantman_private-docker-redirector.arn}",
        "name": "${aws_ecr_repository.jantman_private-docker-redirector.name}",
        "registry_id": "${aws_ecr_repository.jantman_private-docker-redirector.registry_id}",
        "url": "${aws_ecr_repository.jantman_private-docker-redirector.url}"
      }
    }
  }
}

fails with:

* ecr_jantman_private-docker-redirector: output has invalid keys: registry_id, url, arn, name
* ecr_jantman_private-docker-redirector: output is missing required 'value' key

But infra_ecr.tf:

resource "aws_ecr_repository" "jantman_private-docker-redirector" {
  name = "jantman/private-docker-redirector"
}

output "ecr_jantman_private-docker-redirector" {
  value = {
    "arn" = "${aws_ecr_repository.jantman_private-docker-redirector.arn}",
    "name" = "${aws_ecr_repository.jantman_private-docker-redirector.name}",
    "registry_id" = "${aws_ecr_repository.jantman_private-docker-redirector.registry_id}",
    "url" = "${aws_ecr_repository.jantman_private-docker-redirector.url}"
  }
}

works fine.

I understand that this is an open bug, however may I suggest at least updating these docs? The following statement is particularly misleading
The downsides of JSON are less human readability and the lack of comments. Otherwise, the two are completely interoperable.
lost some time writing some codgen, assumed that statement was accurate.

Hi all! Sorry for the weird behavior and the long silence here.

This seems to be the same as #9555, which I closed today after verifying that it is fixed in Terraform v0.12.0-alpha1. I posted some more details in a comment in the other issue. The fix will also be included in the final v0.12.0 release. Thanks for reporting the issue, and sorry again for the slow response.

as pointed out here: https://github.com/hashicorp/terraform/issues/9239#issuecomment-266831517

test_map in json has to be defined:

{"test_map": [{
   "key1": [{
     "index1": "data1", 
     "index2": "data2",
   }],
   "key2": [{
     "index1": "data1",
   }],
 }]}

for my use case this wokrs like a charm.

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