0
votes

I am trying to do something like below.

  dynamic "volume" {
    for_each = var.volumes
    content {
      host_path = lookup(volume.value, "host_path", null)
      name      = volume.value.name

      dynamic "efs_volume" {
        for_each = var.efs_volumes
        content {
          name = efs_volume.value.name
          efs_volume_configuration {
            file_system_id     = efs_volume.value.file_system_id
            root_directory     = efs_volume.value.root_directory
            transit_encryption = efs_volume.value.transit_encryption != "ENABLED" ? "" : "ENABLED"
            dynamic "authorization_config" {
              for_each = efs_volume.value.access_point_id != "" ? [1] : []
              content {
                access_point_id = volume.value.access_point_id
              }
            }
          }
        }
      }
    }
  }

Its giving me,

Error: Unsupported block type

Blocks of type "efs_volume" are not expected here

Can anyone point me what is wrong here? I am using terraform 0.12.24.

Please note, I know that "authorization_config" still not supported by AWS provider, I hope the feature will be coming soon as I have seen the github pull request. Hence, I'm preparing my code compatibility. Basically, what I need is to mount both host and EFS volumes into my ECS task definition.

EDIT

I updated the code as you said.

  dynamic "volume" {
    for_each = var.volumes
    content {
      host_path = lookup(volume.value, "host_path", null)
      name      = volume.value.name

      dynamic "efs_volume_configuration" {
        for_each = lookup(volume.value, "efs_volume_configuration", [])
        content {
          file_system_id = lookup(efs_volume_configuration.value, "file_system_id", null)
          root_directory = lookup(efs_volume_configuration.value, "root_directory", null)
        }
      }
    }
  }```

Now the problem is, 

> efs_volume_configuration

getting added to each volume block. Which actually need to be null.

```      + volume { # forces replacement
          + host_path = "/var/run"
          + name      = "docker-sock-folder"

          + efs_volume_configuration {}
        }
      + volume { # forces replacement
          + host_path = "/var/run/docker/netns"
          + name      = "docker-netns"

          + efs_volume_configuration {}
        }
      + volume { # forces replacement
          + name = "efs_share"

          + efs_volume_configuration {
              + file_system_id = "fs-xxxxxx"
              + root_directory = "/"
            }
        }

EDIT

Here is my varaibles..

  type = list(object({
    name      = string
    host_path = string
    efs_volume_configuration = list(object({
      file_system_id = string
      root_directory = string
    }))
  }))
  description = "Task volume definitions as list of configuration objects"
  default = [
    {
      "name" : "data-folder",
      "host_path" : "/var/lib/data",
      "efs_volume_configuration" = [
        {
          "file_system_id" : "",
          "root_directory" : ""
        }
      ]
    },
    {
      "name" : "docker-sock-folder",
      "host_path" : "/var/run",
      "efs_volume_configuration" = [
        {
          "file_system_id" : "",
          "root_directory" : ""
        }
      ]
    },
    {
      "name" : "efs_share",
      "host_path" : null,
      "efs_volume_configuration" = [
        {
          "file_system_id" : "fs-xxxxxx",
          "root_directory" : "/"
        }
      ]
    }

....
1

1 Answers

2
votes

For ecs task definition resource efs_volume is not a supported argument. If you looking for a fully working module, perhaps module I have written that works well and is published to terraform registry may help. https://github.com/umotif-public/terraform-aws-ecs-fargate-task-definition/blob/master/main.tf#L157

To use efs volumes you can define following dynamic block:

dynamic "volume" {
for_each = var.volume
content {
  name      = volume.value.name
  host_path = lookup(volume.value, "host_path", null)

  dynamic "docker_volume_configuration" {
    for_each = lookup(volume.value, "docker_volume_configuration", [])
    content {
      scope         = lookup(docker_volume_configuration.value, "scope", null)
      autoprovision = lookup(docker_volume_configuration.value, "autoprovision", null)
      driver        = lookup(docker_volume_configuration.value, "driver", null)
      driver_opts   = lookup(docker_volume_configuration.value, "driver_opts", null)
      labels        = lookup(docker_volume_configuration.value, "labels", null)
    }
  }

  dynamic "efs_volume_configuration" {
    for_each = lookup(volume.value, "efs_volume_configuration", [])
    content {
      file_system_id = lookup(efs_volume_configuration.value, "file_system_id", null)
      root_directory = lookup(efs_volume_configuration.value, "root_directory", null)
    }
  }
}

In this case efs_volume_configuration is a support block. Once you have that in your module, you can pass in efs config in the following way:

module "ecs-task-definition" {
...
  volume = [
    {
      name = "efs-html",
      efs_volume_configuration = [
        {
          "file_system_id" : "efs_id",
          "root_directory" : "/usr/share/nginx"
        }
      ]
    }
  ]
}

Important: you need at least version v2.64.0 of terraform aws provider.