0
votes

In terraform I am attempting to pass a variable (list) to a module that we built. This variable needs to be used within a aws_ecs_task_definition resource in the container_definitions.
Right now I am just starting with an empty default list defined as a variable:

variable "task_enviornment" {
  type        = "list"
  default = []
}

My ECS task definition looks like this:

resource "aws_ecs_task_definition" "ecs_task_definition" {
  family                   = "${var.ecs_family}"
  network_mode             = "awsvpc"
  task_role_arn            = "${aws_iam_role.iam_role.arn}"
  execution_role_arn       = "${data.aws_iam_role.iam_ecs_task_execution_role.arn}"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "${var.fargate_cpu}"
  memory                   = "${var.fargate_memory}"

  container_definitions =<<DEFINITION
  [
    {
      "cpu": ${var.fargate_cpu},
      "image": "${var.app_image}",
      "memory": ${var.fargate_memory},
      "name": "OURNAME",
      "networkMode": "awsvpc",
      "environment": "${jsonencode(var.task_enviornment)}",
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group" : "${aws_cloudwatch_log_group.fargate-logs.name}",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "demo"
        }
      },
      "portMappings": [
        {
        "containerPort": ${var.app_port},
        "hostPort": ${var.app_port}
        }
      ]
    }
  ]
  DEFINITION
}

The part I am having a problem with with the "environment" part:

"environment": "${jsonencode(var.task_enviornment)}",

I have tried a few different ways to get this to work.

If I do "environment": "${jsonencode(var.task_enviornment)}", I get ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal string into Go struct field ContainerDefinition.Environment of type []*ecs.KeyValuePair

If I do "environment": "${var.task_enviornment}", or "environment": ["${var.task_enviornment}"],
I get At column 1, line 1: output of an HIL expression must be a string, or a single list (argument 8 is TypeList) in: Then it just outputs the contents of container_definitions

I did also try adding default values and I was getting similar error messages. However I do need to be able to handle no values being sent in, so an empty list.

variable "task_enviornment" {
  type        = "list"
  default = [
    {
      "name" = "BUCKET",
      "value" = "test"
    }
  ]
}
3
Theres also a typo in environment.Chun

3 Answers

2
votes

After a lot of investigation and a fresh set of eyes looking at this figured out the solution. I am unsure why this fixes it, and I feel like this is likely a bug.
Needed to do 2 things to fix this.

  1. Remove type = "list" from the variable definition.

    variable "task_environment" { default = [] }

  2. Remove the quotes when using the variable:
    "environment": ${jsonencode(var.task_environment)},

0
votes

The below solution should work

in variable.tf

variable "app_environments_vars" {
type        = list(map(string))
default     = []
description = "environment varibale needed by the application"
default = [
{
  "name" = "BUCKET",
  "value" = "test"
},{
  "name" = "BUCKET1",
  "value" = "test1"
}]

and in your task definition, you can use ${jsonencode(var.app_environments_vars)} similar to

container_definitions =<<DEFINITION
  [
    {
      "cpu": ${var.fargate_cpu},
      "image": "${var.app_image}",
      "memory": ${var.fargate_memory},
      "name": "OURNAME",
      "networkMode": "awsvpc",
      "environment": ${jsonencode(var.envoy_environments_vars)},
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group" : "${aws_cloudwatch_log_group.fargate-logs.name}",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "demo"
        }
      },
      "portMappings": [
        {
        "containerPort": ${var.app_port},
        "hostPort": ${var.app_port}
        }
      ]
    }
  ]
0
votes

My guess is that you are trying to use the type "map" instead of lists, as showed above, the removal from type specification will work. Example:

  • List_sample = [1,2,3]
  • Map_sample = { key_name = "value" }

Reference: Terraform - Type Constraints