Search code examples
amazon-web-servicesterraformamazon-ecsterraform-provider-aws

How to retrieve the public IP address of an AWS ECS contrainer using Terraform


How do I pull the public IP address assigned to a container of an AWS ECS cluster/service?

For testing purposes I do not want to spin up an ALB, so I just added service to a public subnet. The best I was able to come up with so far is to use aws cli to pull the IP address. I am wondering if there's a way to pull this somehow using Terraform attributes.

resource "aws_ecs_cluster" "this" {
  name = "${lower(var.app_name)}-${lower(var.app_environment)}-cluster"
  
}

resource "aws_ecs_task_definition" "this" {
  family                   = "${lower(var.app_name)}-${lower(var.app_environment)}-task"
  execution_role_arn       = aws_iam_role.ecs_task_execution_role.arn
  container_definitions    = jsonencode([{
    name            = "${lower(var.app_name)}-${lower(var.app_environment)}-container"
    image           = "nginx:latest"
    portMappings    = [{ containerPort = 80 }]
  }])
  memory                   = 3072
  cpu                      = 1024
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"

  runtime_platform {
    operating_system_family = "LINUX"
    cpu_architecture        = "X86_64"
  }
}

resource "aws_ecs_service" "this" {
  name            = "${lower(var.app_name)}-${lower(var.app_environment)}-service"
  cluster         = aws_ecs_cluster.this.id
  task_definition = aws_ecs_task_definition.this.arn
  desired_count   = 1

  # Assign an Elastic IP address to the task
  network_configuration {
    assign_public_ip = true
    subnets          = [module.vpc100.public_subnet1_id,module.vpc100.public_subnet2_id]
    security_groups  = [aws_security_group.this.id]
  }

  # Configure the service to use Fargate
  launch_type = "FARGATE"

  tags = {
    Name = "${lower(var.app_name)}-${lower(var.app_environment)}-container"
  }

}

# My hack to pull the public IP address
resource "terraform_data" "publicip" {
  provisioner "local-exec" {
    command = <<EOF
        clustername=${lower(var.app_name)}-${lower(var.app_environment)}-cluster
        taskid=$(aws ecs list-tasks --cluster $clustername --query "taskArns[0]" --output text)
        eni=$(aws ecs describe-tasks --tasks $taskid --cluster example6-dev-cluster --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text)
        publicip=$(aws ec2 describe-network-interfaces --query "NetworkInterfaces[?NetworkInterfaceId=='$eni'].Association.PublicIp" --output text)
        echo "$publicip"
    EOF
  }
  depends_on = [
    aws_ecs_service.this
  ]
}

Solution

  • You can't do that with Terraform. Terraform just knows that it told AWS to create a service. It doesn't know anything about any current tasks that are being managed by the service. You'll need to run something like an AWS CLI command after your terraform apply is complete.