Skip to content

Commit

Permalink
Add IAC part 1 (#100)
Browse files Browse the repository at this point in the history
* Add iac folder

* Generate terraform lock file and add batch role

* Add compute resources for batch

* Add dumped db

* Add instructions about manual resources in README

* Add terraform plan as iac test

* Add alb and ecs

* Add ECR parameter

* Add iac deploy

* Add default tags

* Complete deployment instructions
  • Loading branch information
campos20 committed Aug 5, 2023
1 parent d5163c7 commit 91957c4
Show file tree
Hide file tree
Showing 24 changed files with 757 additions and 6 deletions.
30 changes: 24 additions & 6 deletions .github/workflows/backdeploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,31 @@ jobs:
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and push
- name: Build and push to ECR
uses: docker/build-push-action@v2
with:
context: ./server
file: ./server/Dockerfile
push: true
tags: thewca/statistics-server:latest
run: |
cd server
./gradlew clean build --info -x test
export STAGE=prod
GIT_HASH=$(git rev-parse --short HEAD)
# Get value from ssm and export it
ECR_URL_PARAM=$(aws ssm get-parameter --name "/$STAGE/ecr/url/statistics_server")
ECR_URL=$(echo $ECR_URL_PARAM | jq -r '.Parameter.Value')
# Before and after the bar
ECR_URL_ROOT="${ECR_URL%%/*}"
ECR_URL_SPEC="${ECR_URL##*/}"
aws ecr get-login-password --region ${{ env.AWS_DEFAULT_REGION }} | docker login --username AWS --password-stdin $ECR_URL_ROOT
docker build -t $ECR_URL_SPEC .
docker tag $ECR_URL_SPEC:latest $ECR_URL:latest
docker tag $ECR_URL_SPEC:latest $ECR_URL:$GIT_HASH
docker push $ECR_URL:latest
docker push $ECR_URL:$GIT_HASH
- name: Blue green deployment
run: |
export AWS_ACCESS_KEY_ID=${{ secrets.CI_CD_AWS_ACCESS_KEY_ID }}
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/iacdeploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: IAC Deploy

on:
push:
branches:
- main
paths:
- "iac/**"
- ".github/workflows/iacdeploy.yaml"

env:
STAGE: prod
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.CI_CD_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_CD_AWS_SECRET_ACCESS_KEY }}

defaults:
run:
working-directory: iac

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: hashicorp/setup-terraform@v2
- run: terraform init
- name: Select workspace and apply app
run: |
terraform workspace select $STAGE || terraform workspace new $STAGE
terraform apply --auto-approve
34 changes: 34 additions & 0 deletions .github/workflows/iactest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Test terraform

env:
STAGE: prod
ENV: -prod
AWS_DEFAULT_REGION: ${{ env.AWS_DEFAULT_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.CI_CD_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_CD_AWS_SECRET_ACCESS_KEY }}

on:
pull_request:
branches:
- main
paths:
- "iac/**"
- ".github/workflows/iactest.yaml"

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: hashicorp/setup-terraform@v2
- name: Replace bucket name
run: |
sed -i "s|bucket = \"NON-EXISTING-BUCKET\"|bucket = \"${{ env.IAC_BUCKET_NAME }}\"|g" iac/main.tf
- run: terraform init
- name: Change workspace
run: |
terraform workspace select $STAGE || terraform workspace new $STAGE
- name: Plan
run: |
terraform plan -out tfapply
1 change: 1 addition & 0 deletions iac/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.terraform/
25 changes: 25 additions & 0 deletions iac/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions iac/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Statistics IAC

This is the IAC for the statistics project, using terraform and AWS.

## Requirements

- Terraform
- AWS account

## Setup

- Create a bucket and replace its name in `iac/main.tf`.

- Install [terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started)

- Start terraform

`terraform init`

- Create or select new workspace

`terraform workspace select prod || terraform workspace new prod`

- Run plan

`terraform plan`

## Resources created manually

To avoid the usage of variables in terraform (like tfvars), some resources are created manually and referenced here. You need to create them and run the project (or run when there are changes in the variables).

```bash
export region=us-west-2
export environment=prod
export app_id="SOME_APP_ID_HERE"
export write_user="USERNAME_HERE"
export write_password="STRONG_PASSWORD_HERE"
export read_user="USERNAME_HERE"
export read_password="ANOTHER_STRONG_PASSWORD_HERE"

```

```bash
aws ssm put-parameter --name "/config/$environment/statistics/app/id" --value $app_id --overwrite --region $region --type String
aws ssm put-parameter --name "/config/$environment/statistics/dumped_db/write_user" --value $write_user --overwrite --region $region --type String
aws ssm put-parameter --name "/config/$environment/statistics/dumped_db/write_password" --value $write_password --overwrite --region $region --type String
aws ssm put-parameter --name "/config/$environment/statistics/dumped_db/read_user" --value $read_user --overwrite --region $region --type String
aws ssm put-parameter --name "/config/$environment/statistics/dumped_db/read_password" --value $read_password --overwrite --region $region --type String
```
68 changes: 68 additions & 0 deletions iac/alb.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
resource "aws_alb" "statistics_server_load_balancer" {
name = "statistics-server-alb-${terraform.workspace}"
subnets = [aws_default_subnet.default_az1.id, aws_default_subnet.default_az2.id]
security_groups = [aws_security_group.http_security_group.id]
load_balancer_type = "application"
}

resource "aws_alb_target_group" "statistics_server_target_group" {
name_prefix = "stattg"
port = var.default_tomcat_port
protocol = "HTTP"
vpc_id = aws_default_vpc.default.id
target_type = "ip"

lifecycle {
create_before_destroy = true
}

health_check {
healthy_threshold = "3"
interval = "30"
protocol = "HTTP"
matcher = "200"
timeout = "3"
path = "/actuator/health"
unhealthy_threshold = "2"
}
}

resource "aws_alb_target_group" "statistics_server_target_group_blue_green" {
name_prefix = "stttg2"
port = var.default_tomcat_port
protocol = "HTTP"
vpc_id = aws_default_vpc.default.id
target_type = "ip"

lifecycle {
create_before_destroy = true
}

health_check {
healthy_threshold = "3"
interval = "30"
protocol = "HTTP"
matcher = "200"
timeout = "3"
path = "/actuator/health"
unhealthy_threshold = "2"
}
}

data "aws_acm_certificate" "statistics_server_cetificate" {
domain = "statistics-api.worldcubeassociation.org"
statuses = ["ISSUED"]
}

resource "aws_alb_listener" "statistics_server_https_listener" {
load_balancer_arn = aws_alb.statistics_server_load_balancer.arn
port = var.https_port
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = data.aws_acm_certificate.statistics_server_cetificate.arn

default_action {
target_group_arn = aws_alb_target_group.statistics_server_target_group.id
type = "forward"
}
}
72 changes: 72 additions & 0 deletions iac/batch.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
resource "aws_iam_role" "ecs_instance_role" {
name = "ecs-instance-role-${terraform.workspace}"

assume_role_policy = templatefile("${path.module}/templates/policies/assume-role-ec2.json", {})
}

resource "aws_iam_instance_profile" "ecs_instance_role" {
name = "ecs-instance-role-${terraform.workspace}"
role = aws_iam_role.ecs_instance_role.name
}

resource "aws_iam_role" "statistics_cron_service_role" {
name = "statistics-cron-service-role-${terraform.workspace}"

assume_role_policy = templatefile("${path.module}/templates/policies/assume-role-batch.json", {})
}

resource "aws_iam_role_policy_attachment" "statistics_cron_service_role" {
role = aws_iam_role.statistics_cron_service_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole"
}

resource "aws_batch_compute_environment" "statistics_cron_compute_environment" {
type = "MANAGED"
compute_environment_name = "statistics-cron-compute-environment-${terraform.workspace}"
state = "ENABLED"
service_role = aws_iam_role.statistics_cron_service_role.arn

compute_resources {
max_vcpus = 4

security_group_ids = [aws_security_group.all_out.id]

subnets = [
aws_default_subnet.default_az1.id,
aws_default_subnet.default_az2.id
]

type = "FARGATE"
}

depends_on = [aws_iam_role_policy_attachment.statistics_cron_service_role]
}

resource "aws_batch_job_queue" "statistics_cron_job_queue" {
name = "statistics-cron-job-queue-${terraform.workspace}"
state = "ENABLED"
priority = 1
compute_environments = [aws_batch_compute_environment.statistics_cron_compute_environment.arn]
}

resource "aws_batch_job_definition" "statistics_cron_job_definition" {
name = "statistics-cron-job-definition-${terraform.workspace}"
type = "container"
platform_capabilities = ["FARGATE"]

container_properties = templatefile("./templates/batch/statistics_cron.json.tpl", {
image = "${aws_ecr_repository.statistics_cron.repository_url}:latest"
statistics_port = "8080"
db_port = "3306"
db_host = aws_db_instance.dumped_db.address
db_name = "wca_development"
db_username = data.aws_ssm_parameter.dumped_db_write_user.value
db_password = data.aws_ssm_parameter.dumped_db_write_password.value
execution_role = aws_iam_role.ecs_task_execution_role.arn
})
}

resource "aws_iam_role" "ecs_task_execution_role" {
name = "ecs-task-execution-role-${terraform.workspace}"
assume_role_policy = templatefile("${path.module}/templates/policies/assume-role-ecs.json", {})
}
19 changes: 19 additions & 0 deletions iac/data-ssm.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
data "aws_ssm_parameter" "statistics_app_id" {
name = "/config/${terraform.workspace}/statistics/app/id"
}

data "aws_ssm_parameter" "dumped_db_write_user" {
name = "/config/${terraform.workspace}/statistics/dumped_db/write_user"
}

data "aws_ssm_parameter" "dumped_db_write_password" {
name = "/config/${terraform.workspace}/statistics/dumped_db/write_password"
}

data "aws_ssm_parameter" "dumped_db_read_user" {
name = "/config/${terraform.workspace}/statistics/dumped_db/read_user"
}

data "aws_ssm_parameter" "dumped_db_read_password" {
name = "/config/${terraform.workspace}/statistics/dumped_db/read_password"
}
35 changes: 35 additions & 0 deletions iac/ecr.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
resource "aws_ecr_repository" "statistics_cron" {
name = "statistics-cron-${terraform.workspace}"

image_scanning_configuration {
scan_on_push = true
}

tags = {
(var.type) = var.type_ecr
}
}

resource "aws_ecr_lifecycle_policy" "expire_images_statistics_cron" {
repository = aws_ecr_repository.statistics_cron.name

policy = templatefile("./templates/ecr/expire-policy.json", {})
}

resource "aws_ecr_repository" "statistics_server" {
name = "statistics-server-${terraform.workspace}"

image_scanning_configuration {
scan_on_push = true
}

tags = {
(var.type) = var.type_ecr
}
}

resource "aws_ecr_lifecycle_policy" "expire_images_statistics_server" {
repository = aws_ecr_repository.statistics_server.name

policy = templatefile("./templates/ecr/expire-policy.json", {})
}
Loading

0 comments on commit 91957c4

Please sign in to comment.