Terraform: aws_ecs_task_definition fails to decode container_definitions JSON with numeric strings

Created on 22 Jan 2016  ·  10Comments  ·  Source: hashicorp/terraform

This is somewhat of a minor quibble, but since it represents a potentially-common use case, I thought I should raise it. When defining an AWS ECS Task Definition, I'll often use the AWS console tool to generate initial JSON, then paste it into a local file for Terraform to manage.

The JSON generated by this tool serializes numeric fields (such as memory and portMappings[hostPort]) as strings instead of integers, like so:

{
    "containerDefinitions": [
        {
            "name": "terraform-issue-example",
            "image": "terraform-issue-example",
            "memory": "123",
            "portMappings": [
                {
                    "hostPort": "123",
                    "containerPort": "123",
                    "protocol": "tcp"
                }
            ],
            "environment": null,
            "mountPoints": null,
            "volumesFrom": null,
            "extraHosts": null,
            "logConfiguration": null,
            "ulimits": null,
            "dockerLabels": null
        }
    ],
    "volumes": []
}

When I copy the container_definitions array from this JSON and define an aws_ecs_task_definition to load it, running terraform apply results in:

Error decoding JSON: json: cannot unmarshal string into Go value of type int64

Once I edit the JSON to remove all the quotes around integer values, terraform apply succeeds.

enhancement provideaws

Most helpful comment

Interestingly you can actually interpolate the memory value but without the quotes.

Something like:

[
  {
    "name": "busybox",
    "image": "${docker_image}",
    "cpu": ${cpu},
    "memory": ${memory}
  }
]

All 10 comments

+1. It would be great to have this enhancement

👍

I couldn't manage to parametrize the configuration of some elements using a template. That would be really cool if we could do it :

[
  {
    "name": "busybox",
    "image": "${docker_image}",
    "cpu": "${cpu}",
    "memory": "${memory}"
  }
]

Interestingly you can actually interpolate the memory value but without the quotes.

Something like:

[
  {
    "name": "busybox",
    "image": "${docker_image}",
    "cpu": ${cpu},
    "memory": ${memory}
  }
]

Thanks to @ekowcharles for pointing out you can interpolate with out quotes.

I think this should be an enhancement to the docs. I'm able to pram the my task definitions file like so.

[
  {
    "name": "${container_name}",
    "image": "${format("%s/%s:%s", url, docker_image, docker_tag)}",
    "cpu": ${container_cpu},
    "memory": ${container_memory},
    "essential": true,
    "portMappings": [
      {
        "containerPort": ${container_port},
        "hostPort": ${container_host_port}
      }
    ],
    "dockerLabels": {
      "app": "${container_app_label}"
    }
  }
]

And the above works just fine.

Looking at the ECS Task Definitions prams here

memory - int
cpu - int
containerPort - int
hostPort - int

If you try and put them as strings you will get the following message

Error applying plan:

1 error(s) occurred:

* aws_ecs_task_definition.node: Error decoding JSON: json: cannot unmarshal string into Go value of type int64

I hope this helps others.

J

Well isn't that interesting. Now the opposite generates an error:

...
      {
        "name": "PORT",
        "value": 80
      },
...

This was driving me crazy.... the solution as stated by @xsmaster is not to use quotation marks around around values that should render as integers

I don't think that not having the quotation marks around the interpolation is adequate, as now my IDE cannot parse the JSON properly and can't tell me of any issues I might have. We need terraform to be able to figure out that a variable is a number being injected and remove the quotation marks automatically like it does for everything else within tf files.

I'm also fairly certain this used to work properly...

Hi all! Sorry for the very long silence here.

I'm just looking over some older issues that we've missed when posting updates in the past due to them having an outdated labeling scheme.

I believe the main issue discussed in the original comment here is a result of some AWS provider behavior: it decodes the container definiton JSON into an in-memory model object provided by the AWS SDK in order to normalize it to prevent semantically-insignificant formatting changes from causing unnecessary diffs. In the process of doing that, it imposes the validation constraints specified by that, which includes treating these port numbers (in PortMappings as integers.

Since this is a consequence of code in the AWS provider, I'm going to have our bot move this issue into the AWS provider repository and let the maintainers of that provider decide what is best to do about it.


Some of you are also discussing the fact that interpolating values into a raw JSON string is inconvenient and error-prone. On that subject, the forthcoming Terraform 0.12.0 release will include a generalized jsonencode function that will no longer have the type constraints imposed by that function in Terraform 0.11, so in principle you could generate the JSON programmatically in Terraform config to avoid the need to template directly into a JSON string:

resource "aws_ecs_task_definition" "service" {
  family                = "service"
  container_definitions = jsonencode([
    {
      name = "busybox"
      image = var.docker_image
      cpu = var.cpu
      memory = var.memory
      # etc
    },
  ])

  # ... etc, etc ...

This issue has been automatically migrated to terraform-providers/terraform-provider-aws#6380 because it looks like an issue with that provider. If you believe this is _not_ an issue with the provider, please reply to terraform-providers/terraform-provider-aws#6380.

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