# Terraform configuration to run an ECS task on AWS Fargate.

provider "aws" {
  region = "us-east-1"
}

# --- 1. VPC and Subnets ---
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "my-terraform-fargate-vpc"
  }
}

resource "aws_subnet" "public_1" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "my-terraform-fargate-public-1"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "my-terraform-fargate-igw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "my-terraform-fargate-public-rt"
  }
}

resource "aws_route_table_association" "public_1" {
  subnet_id      = aws_subnet.public_1.id
  route_table_id = aws_route_table.public.id
}

# --- 2. Security Group for Fargate Task ---
resource "aws_security_group" "fargate_sg" {
  name        = "MyTerraformFargateSG"
  description = "Allow HTTP for Fargate task"
  vpc_id      = aws_vpc.main.id

  ingress {
    description = "HTTP from anywhere"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "MyTerraformFargateSG"
  }
}

# --- 3. ECS Cluster ---
resource "aws_ecs_cluster" "main" {
  name = "my-terraform-fargate-cluster"

  tags = {
    Name = "MyTerraformFargateCluster"
  }
}

# --- 4. IAM Roles ---
# ECS Task Execution Role
resource "aws_iam_role" "ecs_task_execution_role" {
  name = "MyTerraformFargateTaskExecutionRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect = "Allow",
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        },
        Action = "sts:AssumeRole"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" {
  role       = aws_iam_role.ecs_task_execution_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

# --- 5. Task Definition ---
resource "aws_ecs_task_definition" "nginx_task" {
  family                   = "my-terraform-fargate-task"
  cpu                      = "256"
  memory                   = "512"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  execution_role_arn       = aws_iam_role.ecs_task_execution_role.arn

  container_definitions = jsonencode([
    {
      name        = "nginx-container",
      image       = "nginx:latest",
      portMappings = [
        {
          containerPort = 80,
          hostPort      = 80,
          protocol      = "tcp"
        }
      ]
    }
  ])

  tags = {
    Name = "MyTerraformFargateTask"
  }
}

# --- 6. ECS Service ---
resource "aws_ecs_service" "nginx_service" {
  name            = "my-terraform-nginx-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.nginx_task.arn
  launch_type     = "FARGATE"
  desired_count   = 1

  network_configuration {
    subnets          = [aws_subnet.public_1.id]
    security_groups  = [aws_security_group.fargate_sg.id]
    assign_public_ip = true
  }

  depends_on = [
    aws_iam_role_policy_attachment.ecs_task_execution_role_policy,
  ]

  tags = {
    Name = "MyTerraformNginxService"
  }
}

# --- Outputs ---
output "ecs_cluster_name" {
  value       = aws_ecs_cluster.main.name
  description = "The name of the ECS cluster."
}

output "ecs_service_name" {
  value       = aws_ecs_service.nginx_service.name
  description = "The name of the ECS service."
}

output "fargate_task_public_ip" {
  value = one(aws_ecs_service.nginx_service.network_configuration[0].assign_public_ip ? [
    aws_network_interface.fargate_eni[0].private_ip_address
  ] : [])
  description = "The public IP address of the Fargate task (if assigned)."
}

# This is a workaround to get the public IP of the Fargate task
# as it's not directly exposed by aws_ecs_service.
resource "aws_network_interface" "fargate_eni" {
  count = aws_ecs_service.nginx_service.network_configuration[0].assign_public_ip ? 1 : 0

  attachment {
    instance     = aws_ecs_service.nginx_service.id
    device_index = 0
  }
}
