Grant permissions for ECS Task which is read from json file:
resource "aws_iam_role" "ecstask_role" {
    name = "ecstask_role"
    assume_role_policy = file("./templates/policies/ecstask_role.json")
}
resource "aws_iam_policy" "ecstask_policy" {
    name = "ecstask_policy"
    description = "Policy granting read/write access to ECR repositories"
    policy = file("./templates/policies/ecstask_policy.json")
}
resource "aws_iam_role_policy_attachment" "ecr_policy_attachment" {
    role = aws_iam_role.ecstask_role.name
    policy_arn = aws_iam_policy.ecstask_policy.arn
}
Attach AmazonECSTaskExecutionRolePolicy to allow ecs task running command inside container.
# IAM Policy for ECS Task can execute task
resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" {
    role = aws_iam_role.ecstask_role.name
    policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
Define all neccessary variables first:
locals {
    # ECR repository URL with the 'latest' tag for the web application image
    app_image = "${aws_ecr_repository.web_app_ecr.repository_url}:latest"
    # Name for the container, incorporating the project name for uniqueness
    container_name = "${local.project_name}-frontend"
    # Port on which the containerized application listens (defined in the container image)
    container_port = 80
    # Host port on which the ECS service will expose the container (mapped to container_port)
    host_port = 80
    # Port for the Application Load Balancer in the production environment
    product_port = 80
    # Port for the Application Load Balancer in the pre-production environment
    preproduct_port = 8088
    # vCPU allocation for Fargate tasks, in CPU units (256 = 0.25 vCPU)
    fargate_cpu = "256"
    # Memory allocation for Fargate tasks, in MiB
    fargate_memory = "512"
    # Desired number of running tasks in the ECS service
    desired_count = 1
    # Health check path for the load balancer to verify container health
    health_check_path = "/"
}
Render json template file with Terraform variables. This json file is used for container in Task Definition:
data "template_file" "container_template" {
    template = file("./templates/ecs_container.json.tpl")
    vars = {
        container_name = local.container_name
        app_image = local.app_image
        container_port = local.container_port
        host_port = local.host_port
        fargate_cpu = local.fargate_cpu
        fargate_memory = local.fargate_memory
        aws_region = local.region
    }
}
Creating ECS Cluster and ECS Task Definition:
resource "aws_ecs_cluster" "web_app_cluster" {
    name = "${local.project_name}_cluster"
}
resource "aws_ecs_task_definition" "web_app_task" {
    family = "${local.project_name}-task"
    # ECS Task permission when deploying
    task_role_arn = aws_iam_role.ecstask_role.arn
    # Fargate permission when running
    execution_role_arn = aws_iam_role.ecstask_role.arn
    network_mode = "awsvpc"
    requires_compatibilities = ["FARGATE"]
    cpu = local.fargate_cpu
    memory = local.fargate_memory
    container_definitions = data.template_file.container_template.rendered
}
Export AWS-CLI stress test command:
--profile [your_IAM_user] with your IAM user, created in this step Create IAM User:# List all running task ARNs
output "running_tasks" {
    value = "aws ecs list-tasks --cluster ${aws_ecs_cluster.web_app_cluster.name} --region ${data.aws_region.current.id} --profile lab"
}
# Export the aws cli to test AutoScaling
output "stress_command" {
    value= "aws ecs execute-command --cluster ${aws_ecs_cluster.web_app_cluster.name} --container ${local.container_name} --command 'stress-ng --cpu 0 --timeout 180s' --interactive --region ${data.aws_region.current.id} --profile lab --task [arn_running_task]"
}
ECS cluster runs on private subnet, so we have to setup ECS tasks that only allows inbound access from the ALB (Application Load Balancer) on the specified host port.
# Allow on ALB access to ECS cluster through port 80
resource "aws_security_group" "sg_ecs_tasks" {
    name = "sg_ecs_tasks"
    description = "Allow inbound access from the ALB only"
    vpc_id = module.vpc.vpc_id
    ingress {
        protocol = "tcp"
        from_port = local.host_port
        to_port = local.host_port
        security_groups = [aws_security_group.sg_alb.id]
        description = "Allow access ECS Host port from only ALB"
    }
    egress {
        protocol = "-1"
        from_port = 0
        to_port = 0
        cidr_blocks = ["0.0.0.0/0"]
    }
}