Search code examples
amazon-web-servicesterraformamazon-ecsterraform-provider-awsamazon-elb

Conditionally creating load balancer with ecs service in Terraform


I'm loosely following this example to create a multiple ECS services under one cluster: https://github.com/shashimal/terraform-ecs/blob/master/main.tf

The problem I have is that only some of the services will require a load balancer in front of the service.

I have tried adding a flag (alb_enabled) into the service_config variable like so:

service_config = {
  "test-service-efs" = {
    auto_scaling = {
      scale_in = {
        max_capacity = 1
        min_capacity = 1
        schedule = "00 16 * * ? 2199"
      }
      scale_out = {
        max_capacity = 1
        min_capacity = 1
        schedule = "00 16 * * ? 2199"
      }
    }
    desired_count = 1
    is_public = false
    name = "test-service-efs"

    alb_enabled = false
  }
}
resource "aws_ecs_service" "ecs_service" {
  for_each        = var.service_config
  name            = "${each.value.name}-service"
  cluster         = aws_ecs_cluster.ecs_cluster.id
  task_definition = aws_ecs_task_definition.ecs_task_definition[each.key].arn
  launch_type     = "FARGATE"
  desired_count   = each.value.desired_count

  network_configuration {
    subnets          = var.private_subnets
    assign_public_ip = each.value.is_public 
    security_groups  = var.security_groups
  }

  load_balancer {
    target_group_arn = aws_alb_target_group.alb_target_group[each.key].arn
    container_name   = each.value.name
    container_port   = 3000
  }

  lifecycle {
    ignore_changes = [task_definition,
      tags,
      desired_count
    ]
  }
  tags = var.tags
}

#Dynamically create the alb target groups for app services
resource "aws_alb_target_group" "alb_target_group" {
  for_each = { for k, v in var.service_config : k => v if v.alb_enabled }
  name = "${each.value.name}-tg"
  port = 3000
  protocol = "HTTP"
  target_type = "ip"
  vpc_id = "vpc-xxxxxxxxxxxx"
}

This works fine when the flag is enabled. However when I disable this flag, due to the target group not existing, the ecs_service load balancer fails

Error: Invalid index
on modules\ecs\main.tf line 79, in resource "aws_ecs_service" "ecs_service":
  79:     target_group_arn = aws_alb_target_group.alb_target_group[each.key].arn
    aws_alb_target_group.alb_target_group is object with no attributes
    each.key is "test-service-efs"
The given key does not identify an element in this collection value

I completely understand why this is failing, but I'm struggling to figure out a workaround for it. I was thinking of having two separate ecs modules which create services with and without a load balancer but this could get messy when trying to pass in the various rules to the ALB as variables. There doesn't seem to be a way to set the conditional within the load_balancer section in aws_ecs_service but was wondering does anybody have any creative workarounds for this?


Solution

  • You have to use dynamic blocks to create your block optionally:

     dynamic "load_balancer" {
        for_each = var.service_config[each.key] == true ? [1]: []
        content {
          target_group_arn = aws_alb_target_group.alb_target_group[each.key].arn
          container_name   = each.value.name
          container_port   = 3000
        }
      }