Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terraform rejecting JSON template_file

Tags:

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}"
}

```
like image 890
Michael Quale Avatar asked May 08 '19 18:05

Michael Quale


People also ask

What is Template_file in terraform?

The template_file data source renders a template from a template string, which is usually loaded from an external file. Note. In Terraform 0.12 and later, the templatefile function offers a built-in mechanism for rendering a template from a file.

Does terraform support JSON?

Terraform also supports an alternative syntax that is JSON-compatible. This syntax is useful when generating portions of a configuration programmatically, since existing JSON libraries can be used to prepare the generated configuration files. The JSON syntax is defined in terms of the native syntax.

What does rendered mean in terraform?

rendered - The final rendered template. The value of the policy will be the content of the template after terraform renders it.


1 Answers

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}"
  }
}
like image 171
Maksym Moskvychev Avatar answered Oct 11 '22 21:10

Maksym Moskvychev