Skip to content

Commit

Permalink
feat: cache server
Browse files Browse the repository at this point in the history
  • Loading branch information
xDarksome committed Apr 23, 2024
1 parent fcf7212 commit 147dee1
Show file tree
Hide file tree
Showing 4 changed files with 348 additions and 106 deletions.
201 changes: 201 additions & 0 deletions cache-server/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
variable "vpc_id" {
type = string
}

variable "availability_zone" {
type = string
}

variable "nat_gateway_id" {
type = string
}

locals {
name = "github-actions-cache-server"

hostnum = 4
ip = "10.0.3.${local.hostnum}"

aws_reserved_hostnums = [0, 1, 2, 3, 15] # for '/28' cidr
hostnums_to_reserve = sort(tolist(setsubtract(range(16), concat(local.aws_reserved_hostnums, [local.hostnum]))))

port = 3000
access_token = "cache"
base_url = "http://${local.ip}:${local.port}"
}

resource "aws_subnet" "this" {
vpc_id = var.vpc_id
cidr_block = "10.0.3.0/28"
availability_zone = var.availability_zone
}

# We are attaching all free IP addresses except one to this network interface, effectively forcing ECS
# to assign the specific IP we want to the task.
resource "aws_network_interface" "ip_reserve" {
subnet_id = aws_subnet.this.id
private_ips = [for hostnum in local.hostnums_to_reserve : cidrhost(aws_subnet.this.cidr_block, hostnum)]

tags = {
Name = "${local.name}-ip-reserve"
}
}

resource "aws_route_table" "this" {
vpc_id = var.vpc_id
}

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

resource "aws_route" "nat_gateway" {
route_table_id = aws_route_table.this.id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = var.nat_gateway_id
}

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

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

resource "aws_iam_role" "this" {
name = local.name
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

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

resource "aws_iam_role_policy_attachment" "cloudwatch_write_policy" {
role = aws_iam_role.this.name
policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
}

resource "aws_ecs_cluster" "this" {
name = local.name
}

resource "aws_ecs_cluster_capacity_providers" "this" {
cluster_name = aws_ecs_cluster.this.name

capacity_providers = ["FARGATE_SPOT"]

default_capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
weight = 1
}
}

resource "aws_cloudwatch_log_group" "this" {
name = "${local.name}-logs"
retention_in_days = 1
}

resource "aws_ecs_task_definition" "this" {
family = local.name
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"

container_definitions = jsonencode([{
name = local.name
image = "ghcr.io/falcondev-oss/github-actions-cache-server:1"
essential = true

environment = [
{ name = "URL_ACCESS_TOKEN", value = local.access_token },
{ name = "BASE_URL", value = local.base_url },
{ name = "NITRO_PORT", value = "3000" },
{ name = "STORAGE_DRIVER", value = "s3" },
{ name = "S3_BUCKET", value = aws_s3_bucket.this.bucket },
{ name = "S3_ACCESS_KEY", value = aws_iam_access_key.this.id },
{ name = "S3_SECRET_KEY", value = aws_iam_access_key.this.secret },
{ name = "S3_ENDPOINT", value = "s3.eu-central-1.amazonaws.com" },
{ name = "S3_REGION", value = "eu-central-1" },
{ name = "S3_PORT", value = "443" },
{ name = "S3_USE_SSL", value = "true" },
]

logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.this.name
awslogs-region = "eu-central-1"
awslogs-stream-prefix = "ecs"
}
}
}])

cpu = 1024
memory = 2048
execution_role_arn = aws_iam_role.this.arn

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

resource "aws_ecs_service" "this" {
name = local.name
cluster = aws_ecs_cluster.this.id
task_definition = aws_ecs_task_definition.this.arn
desired_count = 1

deployment_maximum_percent = 100
deployment_minimum_healthy_percent = 0

network_configuration {
subnets = [aws_subnet.this.id]
}
}

resource "aws_iam_user" "this" {
name = local.name
}

resource "aws_iam_access_key" "this" {
user = aws_iam_user.this.name
}

resource "aws_s3_bucket" "this" {
bucket_prefix = "github-actions-cache"
force_destroy = "true"
}

resource "aws_s3_bucket_policy" "this" {
bucket = aws_s3_bucket.this.id

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "${aws_iam_user.this.arn}"
},
"Action": [ "s3:*" ],
"Resource": [
"${aws_s3_bucket.this.arn}",
"${aws_s3_bucket.this.arn}/*"
]
}
]
}
EOF
}

output "url" {
value = "${local.base_url}/${local.access_token}/"
}
127 changes: 22 additions & 105 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,27 @@ variable "repo_url" {
}

variable "labels" {
type = string
type = string
default = null
}

variable "desired_count" {
type = number
type = number
default = null
}

locals {
availability_zone = "eu-central-1a"
}

resource "aws_vpc" "this" {
cidr_block = "10.0.0.0/16"
}

# Public subnet

resource "aws_subnet" "public" {
vpc_id = aws_vpc.this.id
cidr_block = "10.0.1.0/24"
vpc_id = aws_vpc.this.id
cidr_block = "10.0.1.0/24"
availability_zone = local.availability_zone
}

resource "aws_route_table" "public" {
Expand All @@ -89,17 +94,6 @@ resource "aws_route_table_association" "public" {
route_table_id = aws_route_table.public.id
}

# Private subnet

resource "aws_subnet" "private" {
vpc_id = aws_vpc.this.id
cidr_block = "10.0.2.0/24"
}

resource "aws_route_table" "private" {
vpc_id = aws_vpc.this.id
}

resource "aws_eip" "this" {}

resource "aws_nat_gateway" "this" {
Expand All @@ -109,96 +103,19 @@ resource "aws_nat_gateway" "this" {
depends_on = [aws_internet_gateway.this]
}

resource "aws_route" "nat_gateway" {
route_table_id = aws_route_table.private.id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.this.id
}

resource "aws_route_table_association" "private" {
subnet_id = aws_subnet.private.id
route_table_id = aws_route_table.private.id
module "cache-server" {
source = "./cache-server"
vpc_id = aws_vpc.this.id
availability_zone = local.availability_zone
nat_gateway_id = aws_nat_gateway.this.id
}

# ECS

resource "aws_ecr_repository" "foo" {
name = "github-actions-runner"
}

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

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

resource "aws_iam_role" "this" {
name = "github-actions-runner"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

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

resource "aws_iam_role_policy_attachment" "cloudwatch_write_policy" {
role = aws_iam_role.this.name
policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
}

resource "aws_ecs_cluster" "this" {
name = "github-actions-runners"
}

resource "aws_ecs_cluster_capacity_providers" "example" {
cluster_name = aws_ecs_cluster.this.name

capacity_providers = ["FARGATE_SPOT"]

default_capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
}
}

resource "aws_cloudwatch_log_group" "this" {
name = "github-action-runner-logs"
retention_in_days = 1
}

resource "aws_ecs_task_definition" "this" {
family = "github-actions-runner"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"

container_definitions = jsonencode([{
name = "github-actions-runner"
image = "myoung34/github-runner:ubuntu-focal"
essential = true

logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.this.name
awslogs-region = "eu-central-1"
awslogs-stream-prefix = "ecs"
}
}
}])

cpu = 256
memory = 512
execution_role_arn = aws_iam_role.this.arn

runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "X86_64"
}
module "runner" {
source = "./runner"
vpc_id = aws_vpc.this.id
availability_zone = local.availability_zone
nat_gateway_id = aws_nat_gateway.this.id
cache_url = module.cache-server.url
}

module "run_task" {
Expand Down
2 changes: 1 addition & 1 deletion run_task/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ variable "desired_count" {
}

data "aws_ecs_cluster" "this" {
cluster_name = "github-actions-runners"
cluster_name = "github-actions-runner"
}

data "aws_subnet" "this" {
Expand Down
Loading

0 comments on commit 147dee1

Please sign in to comment.