Michael Quale
Michael Quale

Reputation: 607

Terraform rejecting JSON template_file

The following ECS task definition is being rejected by Terraform during a plan. JSON validates and using the inline container_definitions works fine.

I've Googled and read some commentary that states TF has an issue with JSON objects, mostly related to nesting. I can get around this by placing the JSON into the container_definition directly in the resource block for the task definition, but I would prefer to stick it in a template file.

Error: Error running plan: 1 error(s) occurred:

* module.sonarqube.aws_ecs_task_definition.task: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal string into Go struct field ContainerDefinition.Memory of type int64

JSON Document referenced in template_file:

   {
        "name": "sonarqube",
        "image": "sonarqube:7.5-community",
        "memory": "2048",
        "logConfiguration": {
            "logDriver": "awslogs",
            "options": {
                "awslogs-group": "${log-group}",
                "awslogs-region": "${region}",
                "awslogs-stream-prefix": "ecs"
            }
        },
        "portMappings": {
            "hostPort": "9000",
            "protocol": "tcp",
            "containerPort": "9000"
        },
        "environment": [
            {
                "name": "sonar.jdbc.password",
                "value": "${password}"
            },
            {
                "name": "sonar.jdbc.url",
                "value": "${url}/${extra_url}"
            },
            {
                "name": "sonar.jdbc.username",
                "value": "${username}"
            }
        ]
    }

Relevant TF Blocks:

data "template_file" "task-def" {
  template = "${file("${path.module}/task-def.json")}"

  vars = {
    log-group = "/ecs/${var.cluster_name}-${var.name}"
    region    = "${var.region}"
    url       = "jdbc:postgresql://${var.rds_url}${var.extra_url}"
    username  = "${var.username}"
    password  = "${var.password}"
  }
}
resource "aws_ecs_task_definition" "task" {
  family       = "${var.name}"
  network_mode = "bridge"
  cpu          = "1024"
  memory       = "2048"

  execution_role_arn = "${var.ecs-exec-role}"

  container_definitions = "${data.template_file.task-def.rendered}"
}

```

Upvotes: 5

Views: 8097

Answers (1)

Maksym  Moskvychev
Maksym Moskvychev

Reputation: 1674

Terraform expects Json in a bit dirrerent format. After you fix this it will work:

  1. Memory size and port numbers should be integer, not string
  2. Terraform wants "array with oblects", not a JSON "object"
  3. Variable $extra_url was not imported in template_file.task-def

Fixed version of task-def.json, tested on terraform v0.11.13 and provider.aws v2.9.0:

[
  {
    "name": "sonarqube"
  },
  {
    "image": "sonarqube:7.5-community"
  },
  {
    "memory": 2048
  },
  {
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "tyu",
        "awslogs-region": "tyu",
        "awslogs-stream-prefix": "ecs"
      }
    }
  },
  {
    "portMappings": [
      {
        "hostPort": 9000
      },
      {
        "protocol": "tcp"
      },
      {
        "containerPort": 9000
      }
    ]
  },
  {
    "environment": [
      {
        "name": "sonar.jdbc.password",
        "value": "${password}"
      },
      {
        "name": "sonar.jdbc.url",
        "value": "${url}/${extra_url}"
      },
      {
        "name": "sonar.jdbc.username",
        "value": "${username}"
      }
    ]
  }
]

Fixed version of template_file.task-def:

data "template_file" "task-def" {
  template = "${file("${path.module}/task-def.json")}"

  vars = {
    log-group = "/ecs/${var.cluster_name}-${var.name}"
    region    = "${var.region}"
    url       = "jdbc:postgresql://${var.rds_url}${var.extra_url}"
    username  = "${var.username}"
    password  = "${var.password}"
    extra_url  = "${var.extra_url}"
  }
}

Upvotes: 4

Related Questions