cap 2 tf - varoonsahgal/cg-cloud-foundations GitHub Wiki

TF file:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
  required_version = ">= 1.2.0"
}

provider "aws" {
  region     = "us-west-2"
  access_key = "*****"
  secret_key = "*****"
}

/* ------- S3 Bucket ------ */
resource "aws_s3_bucket" "arev-tf-cp2-bucket-create" {
  bucket = "arev-tf-cp2-bucket"
}

resource "aws_s3_bucket_versioning" "arev-tf-cp2-bucket-verison" {
  bucket = aws_s3_bucket.arev-tf-cp2-bucket-create.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_object" "arev-tf-cp2-bucket-add" {
  for_each = fileset("./jsondata/", "**")
  bucket   = aws_s3_bucket.arev-tf-cp2-bucket-create.id
  key      = each.key
  source   = "./jsondata/${each.value}"
  etag     = filemd5("./jsondata/${each.value}")
}


/* ------- AWS Lambda ------ */
# data "aws_iam_role" "arev-tf-cp2-lambda-role" {
#   name = "room3-capstone2-gettodos-lambda-role"
# }

# data "archive_file" "arev-lambda-zip" {
#   type        = "zip"
#   source_file = "./resources/lambda.py"
#   output_path = "./resources/lambda_function.zip"
# }

# resource "aws_lambda_function" "arev-tf-cp2-lambda-create" {
#   function_name    = "arev-tf-cp2-lambda"
#   filename         = data.archive_file.arev-lambda-zip.output_path
#   source_code_hash = data.archive_file.arev-lambda-zip.output_base64sha256
#   role             = data.aws_iam_role.arev-tf-cp2-lambda-role.arn
#   handler          = "arev-tf-cp2-lambda.lambda_handler"
#   runtime          = "python3.9"
# }


# /* ------- API Gateway ------ */
# resource "aws_api_gateway_rest_api" "arev-tf-cp2-api-create" {

# }


/* ------- ECR Repo ------ */
resource "aws_ecr_repository" "arev-tf-cp2-ecr-repo" {
  name = "arev-tf-cp2-ecr-repo"
}



/* ------- CodeBuild Project ------ */
resource "aws_iam_role" "codebuild-ecr-role" {
  name               = "arev-tf-cp2-cb-role"
  assume_role_policy = data.aws_iam_policy_document.assume-codebuild-policy.json
}

data "aws_iam_policy_document" "assume-codebuild-policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["codebuild.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy" "codebuild-policy" {
  role = aws_iam_role.codebuild-ecr-role.id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Resource": [
        "*"
      ],
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
        "${aws_s3_bucket.codepipeline_bucket.arn}",
        "${aws_s3_bucket.codepipeline_bucket.arn}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecs:UpdateService"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "codebuild-ecr-policy" {
  role       = aws_iam_role.codebuild-ecr-role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser"
}


resource "aws_codebuild_project" "arev-tf-cp2-cb-create" {
  name         = "arev-tf-cp2-codebuild"
  description  = "arev-tf-codebuild-project"
  service_role = aws_iam_role.codebuild-ecr-role.arn

  artifacts {
    type = "NO_ARTIFACTS"
  }

  environment {
    compute_type                = "BUILD_GENERAL1_SMALL"
    image                       = "aws/codebuild/standard:3.0"
    type                        = "LINUX_CONTAINER"
    image_pull_credentials_type = "CODEBUILD"

    privileged_mode = true

    environment_variable {
      name  = "AWS_ACCOUNT_ID"
      value = "962804699607"
    }
    environment_variable {
      name  = "AWS_DEFAULT_REGION"
      value = "us-west-2"
    }
    environment_variable {
      name  = "IMAGE_REPO_NAME"
      value = aws_ecr_repository.arev-tf-cp2-ecr-repo.id
    }
    environment_variable {
      name  = "IMAGE_TAG"
      value = "latest"
    }
    environment_variable {
      name  = "CLUSTER_NAME"
      value = aws_ecs_cluster.arev-tf-cp2-cluster.id
    }
    environment_variable {
      name  = "SERVICE_NAME"
      value = aws_ecs_service.arev-tf-cp2_service.id
    }
  }

  source {
    type            = "GITHUB"
    location        = "https://github.com/stevenng/room3capstone2.git"
    git_clone_depth = 1
  }
}



/* ------- CodePipeline ------ */
resource "aws_codepipeline" "arev-tf-cp2-cp-create" {
  name     = "arev-tf-cp2-codepipeline"
  role_arn = aws_iam_role.codepipeline-service-role.arn

  artifact_store {
    location = aws_s3_bucket.codepipeline_bucket.bucket
    type     = "S3"
  }

  stage {
    name = "Source"

    action {
      name             = "Source"
      category         = "Source"
      owner            = "AWS"
      provider         = "CodeStarSourceConnection"
      version          = "1"
      run_order        = 1
      output_artifacts = ["source_output"]

      configuration = {
        "ConnectionArn"    = aws_codestarconnections_connection.arev-tf-cp2-connection.arn
        "FullRepositoryId" = "tewqs-a/room3capstone2"
        "BranchName"       = "master"
      }
    }
  }

  stage {
    name = "Build"

    action {
      name            = "Build"
      category        = "Build"
      owner           = "AWS"
      provider        = "CodeBuild"
      input_artifacts = ["source_output"]
      version         = "1"
  
      configuration = {
        "ProjectName" = aws_codebuild_project.arev-tf-cp2-cb-create.id
      }
    }
  }
}

resource "aws_s3_bucket" "codepipeline_bucket" {
  bucket = "arev-cp-artifact-bucket"
}

resource "aws_s3_bucket_acl" "codepipeline_bucket_acl" {
  bucket = aws_s3_bucket.codepipeline_bucket.id
  acl    = "private"
}

resource "aws_iam_role" "codepipeline-service-role" {
  name               = "arev-tf-cp2-cp-role"
  assume_role_policy = data.aws_iam_policy_document.assume-codepipeline-policy.json
}

data "aws_iam_policy_document" "assume-codepipeline-policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["codepipeline.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy" "codepipeline_policy" {
  name = "codepipeline_policy"
  role = aws_iam_role.codepipeline-service-role.id

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect":"Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:GetBucketVersioning",
        "s3:PutObjectAcl",
        "s3:PutObject"
      ],
      "Resource": [
        "${aws_s3_bucket.codepipeline_bucket.arn}",
        "${aws_s3_bucket.codepipeline_bucket.arn}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "codestar-connections:UseConnection"
      ],
      "Resource": "${aws_codestarconnections_connection.arev-tf-cp2-connection.id}"
    },
    {
      "Effect": "Allow",
      "Action": [
        "codebuild:BatchGetBuilds",
        "codebuild:StartBuild"
      ],
      "Resource": "*"
    }
  ]
}
EOF
}


/* ------ CodeStar Connection ------ */
resource "aws_codestarconnections_connection" "arev-tf-cp2-connection" {
  name          = "arev-tf-cp2-cs-connection"
  provider_type = "GitHub"
}


# Providing a reference to our default VPC
resource "aws_default_vpc" "default_vpc" {
}

# Providing a reference to our default subnets
resource "aws_default_subnet" "default_subnet_a" {
  availability_zone = "us-west-2a"
}

resource "aws_default_subnet" "default_subnet_b" {
  availability_zone = "us-west-2b"
}

resource "aws_default_subnet" "default_subnet_c" {
  availability_zone = "us-west-2c"
}


resource "aws_ecs_cluster" "arev-tf-cp2-cluster" {
  name = "arev-tf-cp2-cluster" # Naming the cluster
}

resource "aws_ecs_task_definition" "arev-tf-cp2-task" {
  family                   = "arev-tf-cp2-task" # Naming our first task
  container_definitions    = <<DEFINITION
  [
    {
      "name": "arev-tf-cp2-task",
      "image": "${aws_ecr_repository.arev-tf-cp2-ecr-repo.repository_url}",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000
        }
      ],
      "memory": 512,
      "cpu": 256
    }
  ]
  DEFINITION
  requires_compatibilities = ["FARGATE"] # Stating that we are using ECS Fargate
  network_mode             = "awsvpc"    # Using awsvpc as our network mode as this is required for Fargate
  memory                   = 512         # Specifying the memory our container requires
  cpu                      = 256         # Specifying the CPU our container requires
  execution_role_arn       = aws_iam_role.ecsTaskExecutionRole.arn
}

# data "aws_iam_role" "ecsTaskExecutionRole" {
#   name = "ecsTaskExecutionRole"
# }

resource "aws_iam_role" "ecsTaskExecutionRole" {
  name               = "arevTaskExecutionRole"
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
}

data "aws_iam_policy_document" "assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

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

resource "aws_alb" "application_load_balancer" {
  name               = "arev-tf-cp2-alb" # Naming our load balancer
  load_balancer_type = "application"
  subnets = [ # Referencing the default subnets
    "${aws_default_subnet.default_subnet_a.id}",
    "${aws_default_subnet.default_subnet_b.id}",
    "${aws_default_subnet.default_subnet_c.id}"
  ]
  # Referencing the security group
  security_groups = ["${aws_security_group.load_balancer_security_group.id}"]
}

# Creating a security group for the load balancer:
resource "aws_security_group" "load_balancer_security_group" {
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Allowing traffic in from all sources
  }

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

resource "aws_lb_target_group" "target_group" {
  name        = "arev-tf-cp2-tg"
  port        = 80
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_default_vpc.default_vpc.id # Referencing the default VPC
}

resource "aws_lb_listener" "listener" {
  load_balancer_arn = aws_alb.application_load_balancer.arn # Referencing our load balancer
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.target_group.arn # Referencing our target group
  }
}

resource "aws_ecs_service" "arev-tf-cp2_service" {
  name            = "arev-tf-cp2-service"                        # Naming our first service
  cluster         = aws_ecs_cluster.arev-tf-cp2-cluster.id       # Referencing our created Cluster
  task_definition = aws_ecs_task_definition.arev-tf-cp2-task.arn # Referencing the task our service will spin up
  launch_type     = "FARGATE"
  desired_count   = 3 # Setting the number of containers to 3

  load_balancer {
    target_group_arn = aws_lb_target_group.target_group.arn # Referencing our target group
    container_name   = aws_ecs_task_definition.arev-tf-cp2-task.family
    container_port   = 3000 # Specifying the container port
  }

  network_configuration {
    subnets          = ["${aws_default_subnet.default_subnet_a.id}", "${aws_default_subnet.default_subnet_b.id}", "${aws_default_subnet.default_subnet_c.id}"]
    assign_public_ip = true                                                # Providing our containers with public IPs
    security_groups  = ["${aws_security_group.service_security_group.id}"] # Setting the security group
  }
}


resource "aws_security_group" "service_security_group" {
  ingress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"
    # Only allowing traffic in from the load balancer security group
    security_groups = ["${aws_security_group.load_balancer_security_group.id}"]
  }

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