From e8cb0dbce9fb4e985e6e913dc7eda754f203e9f4 Mon Sep 17 00:00:00 2001 From: Altonhe Date: Fri, 26 Jul 2024 20:48:24 -0400 Subject: [PATCH 1/2] PaaS: add deployment on ACI, AWS ECS and Google Cloud Run --- README.md | 18 +- modules/aws-ecs/.terraform.lock.hcl | 19 ++ modules/aws-ecs/main.tf | 200 +++++++++++++++++++++ modules/aws-ecs/readme.md | 68 +++++++ modules/aws-ecs/terraform.tfvars.example | 24 +++ modules/aws-ecs/variables.tf | 116 ++++++++++++ modules/azure-aci/.terraform.lock.hcl | 20 +++ modules/azure-aci/main.tf | 91 ++++++++++ modules/azure-aci/output.tf | 3 + modules/azure-aci/readme.md | 69 +++++++ modules/azure-aci/terraform.tfvars.example | 26 +++ modules/azure-aci/variables.tf | 128 +++++++++++++ modules/gcp-cr/.terraform.lock.hcl | 19 ++ modules/gcp-cr/main.tf | 106 +++++++++++ modules/gcp-cr/output.tf | 3 + modules/gcp-cr/readme.md | 68 +++++++ modules/gcp-cr/terraform.tfvars.example | 21 +++ modules/gcp-cr/variables.tf | 118 ++++++++++++ 18 files changed, 1108 insertions(+), 9 deletions(-) create mode 100644 modules/aws-ecs/.terraform.lock.hcl create mode 100644 modules/aws-ecs/main.tf create mode 100644 modules/aws-ecs/readme.md create mode 100644 modules/aws-ecs/terraform.tfvars.example create mode 100644 modules/aws-ecs/variables.tf create mode 100644 modules/azure-aci/.terraform.lock.hcl create mode 100644 modules/azure-aci/main.tf create mode 100644 modules/azure-aci/output.tf create mode 100644 modules/azure-aci/readme.md create mode 100644 modules/azure-aci/terraform.tfvars.example create mode 100644 modules/azure-aci/variables.tf create mode 100644 modules/gcp-cr/.terraform.lock.hcl create mode 100644 modules/gcp-cr/main.tf create mode 100644 modules/gcp-cr/output.tf create mode 100644 modules/gcp-cr/readme.md create mode 100644 modules/gcp-cr/terraform.tfvars.example create mode 100644 modules/gcp-cr/variables.tf diff --git a/README.md b/README.md index b07208b..00a85cf 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,15 @@ This repo is using [Opentofu](https://opentofu.org/) and other tools to create c ## Platform Support Status -| | VM | Docker | K8s | -|-----------------------|-------------|-----------------|--------------| -| Microsoft Azure | VM ✅ | ACI 🚧 | AKS 🔲 | -| Amazon Web Services | EC2 ✅ | ECS 🚧 | EKS 🔲 | -| Google Cloud Platform | GCE ✅ | GAE 🚧 | GKE 🔲 | -| Render | ❌ | DOCKER ✅(See 1) | ❌ | -| Heroku | ❌ | HCR 🔲 | ❌ | -| DigitalOcean | Droplets 🔲 | CR 🔲 | DOKS 🔲 | -| Native K8s | ❌ | ❌ | K8S ✅(See 2) | +| | VM | Docker | K8s | +|-----------------------|-------------|-------------------|--------------| +| Microsoft Azure | VM ✅ | ACI ✅ | AKS 🔲 | +| Amazon Web Services | EC2 ✅ | ECS(Fargate) ✅ | EKS 🔲 | +| Google Cloud Platform | GCE ✅ | Cloud Run ✅ | GKE 🔲 | +| Render | ❌ | DOCKER ✅🚧(See 1) | ❌ | +| Heroku | ❌ | HCR 🚧 | ❌ | +| DigitalOcean | Droplets 🚧 | CR 🚧 | DOKS 🔲 | +| Native K8s | ❌ | ❌ | K8S ✅(See 2) | The following icons are used to represent the status of support for each platform: - ✅: completed diff --git a/modules/aws-ecs/.terraform.lock.hcl b/modules/aws-ecs/.terraform.lock.hcl new file mode 100644 index 0000000..43df636 --- /dev/null +++ b/modules/aws-ecs/.terraform.lock.hcl @@ -0,0 +1,19 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/aws" { + version = "5.58.0" + hashes = [ + "h1:/NBH5qzIg23xn+xBhXId42rLGeogWx+XaNWEbBdDk7M=", + "zh:2e1c6d710455707c520da58840b0ce24c470437d997ca6843bd0e68ea4c60a4e", + "zh:2f493c86ad9bef82447d0aaa3a17752797e501ca6fb7820964279e8e6e81c8c9", + "zh:8f78e0d3a65213335d1877dacfe05a84f0b4c86de4388ef0a42aa692c7f12df0", + "zh:90f3471a42177db0d7f486698284e6d15bb82c439f2a1b94ae89a0442ff716cc", + "zh:9971dd0b159c8ab5ae16ce3a47b14900040bf7b9ec39b4595c9d2084be65a9ea", + "zh:a3d90643f780c104a0d9e433cfed0658586237d15042c19d7e7038f47adfb1b9", + "zh:ccfb5bc6f860afd0f27562fa10ffa2befa73a23865ff4a904df2f24b77f6dc71", + "zh:daf24a4b651b73d7a0c8fd47d37dd9393d31cb569d1e0cd9917b02f0260df198", + "zh:de574fe5df1d49958f5b14034c30129723b6d1367f7a89eab7e3782320e80f7f", + "zh:fae2e92ea62f41c659a9e26850f1abbb905218358e18a23075a48db73c234eb9", + ] +} diff --git a/modules/aws-ecs/main.tf b/modules/aws-ecs/main.tf new file mode 100644 index 0000000..d164db4 --- /dev/null +++ b/modules/aws-ecs/main.tf @@ -0,0 +1,200 @@ +provider "aws" { + region = var.region +} + +locals { + liveness_probe_path = "/onebusaway-api-webapp/api/where/current-time.json?key=org.onebusaway.iphone" + liveness_probe_port = 8080 + liveness_probe_initial_delay_seconds = 120 + liveness_probe_period_seconds = 30 +} + +resource "aws_vpc" "main" { + cidr_block = "10.0.0.0/16" + enable_dns_hostnames = true +} + +resource "aws_internet_gateway" "main" { + vpc_id = aws_vpc.main.id +} + +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 + } +} + +resource "aws_route_table_association" "public" { + subnet_id = aws_subnet.main.id + route_table_id = aws_route_table.public.id +} + +resource "aws_subnet" "main" { + vpc_id = aws_vpc.main.id + cidr_block = "10.0.1.0/24" + availability_zone = "${var.region}a" + map_public_ip_on_launch = true +} + +resource "aws_security_group" "main" { + vpc_id = aws_vpc.main.id + + ingress { + from_port = 8080 + to_port = 8080 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 2049 + to_port = 2049 + 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"] + } +} + +resource "aws_efs_file_system" "main" { + creation_token = "ecs-efs-oba" +} + +resource "aws_efs_mount_target" "main" { + file_system_id = aws_efs_file_system.main.id + subnet_id = aws_subnet.main.id + security_groups = [aws_security_group.main.id] +} + +resource "aws_ecs_cluster" "main" { + name = var.cluster_name +} + +resource "aws_cloudwatch_log_group" "main" { + name = "/ecs/${var.container_name}" + retention_in_days = 7 +} + +resource "aws_iam_role" "ecs_task_execution_role" { + name = "ecsTaskExecutionRole" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ecs-tasks.amazonaws.com" + } + }] + }) +} + +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" +} + +resource "aws_ecs_task_definition" "main" { + family = var.container_name + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + cpu = var.container_cpu + memory = var.container_memory + execution_role_arn = aws_iam_role.ecs_task_execution_role.arn + + container_definitions = jsonencode([{ + name = var.container_name + image = var.container_image + cpu = var.container_cpu + memory = var.container_memory + memoryReservation = var.container_memory + essential = true + + environment = [ + { name = "TZ", value = var.env_var_tz }, + { name = "GTFS_URL", value = var.env_var_gtfs_url }, + { name = "VEHICLE_POSITIONS_URL", value = var.env_var_vehicle_positions_url }, + { name = "TRIP_UPDATES_URL", value = var.env_var_trip_updates_url }, + { name = "ALERTS_URL", value = var.env_var_alerts_url }, + { name = "REFRESH_INTERVAL", value = var.env_var_refresh_interval }, + { name = "AGENCY_ID", value = var.env_var_agency_id }, + { name = "FEED_API_KEY", value = var.env_var_feed_api_key }, + { name = "FEED_API_VALUE", value = var.env_var_feed_api_value }, + { name = "JDBC_USER", value = var.env_var_jdbc_user }, + { name = "JDBC_PASSWORD", value = var.env_var_jdbc_password }, + { name = "JDBC_URL", value = var.env_var_jdbc_url }, + { name = "GOOGLE_MAPS_API_KEY", value = var.env_var_google_maps_api_key }, + { name = "GOOGLE_MAPS_CHANNEL_ID", value = var.env_var_google_maps_channel_id }, + { name = "GOOGLE_MAPS_CLIENT_ID", value = var.env_var_google_maps_client_id }, + ] + + portMappings = [ + { + containerPort = 8080 + hostPort = 8080 + protocol = "tcp" + } + ] + + mountPoints = [ + { + sourceVolume = "bundle" + containerPath = "/bundle" + readOnly = false + } + ] + + healthCheck = { + command = ["CMD-SHELL", "curl -f http://localhost:8080${local.liveness_probe_path} || exit 1"] + interval = local.liveness_probe_period_seconds + timeout = 5 + retries = 3 + startPeriod = local.liveness_probe_initial_delay_seconds + } + + logConfiguration = { + logDriver = "awslogs" + options = { + "awslogs-group" = "/ecs/${var.container_name}" + "awslogs-region" = var.region + "awslogs-stream-prefix" = "ecs" + } + } + }]) + + volume { + name = "bundle" + + efs_volume_configuration { + file_system_id = aws_efs_file_system.main.id + root_directory = "/" + } + } + + depends_on = [ + aws_efs_file_system.main, aws_efs_mount_target.main + ] +} + +resource "aws_ecs_service" "main" { + name = var.service_name + cluster = aws_ecs_cluster.main.id + task_definition = aws_ecs_task_definition.main.arn + desired_count = 1 + launch_type = "FARGATE" + + network_configuration { + subnets = [aws_subnet.main.id] + security_groups = [aws_security_group.main.id] + assign_public_ip = true + } +} diff --git a/modules/aws-ecs/readme.md b/modules/aws-ecs/readme.md new file mode 100644 index 0000000..451af11 --- /dev/null +++ b/modules/aws-ecs/readme.md @@ -0,0 +1,68 @@ +# Deployment Guide for AWS ECS(Fargate) + +AWS ECS is a robust choice for deploying the OneBusAway server, providing a managed container orchestration service that simplifies running and scaling containerized applications. This guide will walk you through deploying the OneBusAway server on AWS ECS using Opentofu. + +## Prerequisites + +1. An AWS account. If you don't have one, you can create a free account [here](https://aws.amazon.com/free/). + +2. AWS CLI. You can install it by following the instructions [here](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html). + +3. Opentofu, an open-source Terraform alternative, you can install it by following the instructions [here](https://opentofu.org/docs/intro/install/). + +4. Ensure you have *ALL* the prerequisites installed before starting the deployment. + +## Steps + +1. Clone this repository to your local machine. You can run: + +```bash +git clone https://github.com/OneBusAway/onebusaway-deployment.git +cd onebusaway-deployment/modules/aws-ecs +``` + +2. Initialize the project. This will download the necessary plugins and providers for the project: + +```bash +tofu init +``` + +3. Create a `terraform.tfvars` file by copying the example variables file, and then modify it according to your needs: + +```bash +cp terraform.tfvars.example terraform.tfvars +``` + +4. Edit the `terraform.tfvars` file and update the variable values to match your specific requirements, such as AWS region, cluster name, container details, and environment variables. + +5. Run Tofu plan to preview the infrastructure changes: + +```bash +tofu plan +``` + +6. Apply the Tofu configuration to create the actual resources: + +```bash +tofu apply +``` + +Type `yes` when prompted to confirm the resource creation. + +7. After the deployment is complete, verify the created resources in the AWS Management Console. Ensure the ECS cluster, tasks, service, and other related resources are created and running correctly. + +8. Access the OneBusAway server by visiting the public IP of the ECS service. You can find the server IP in the AWS Management Console under the ECS service details. + +## Clean up + +If you want to shut down the server and clean up the resources, you can run the following command: + +```bash +tofu destroy +``` + +Opentofu will destroy all resources created by this project, including the ECS cluster, task definition, security groups, and other resources. + +## Conclusion + +This guide shows you how to deploy the OneBusAway server on AWS ECS using Opentofu. If you have any questions or suggestions, feel free to open an issue in this repository. \ No newline at end of file diff --git a/modules/aws-ecs/terraform.tfvars.example b/modules/aws-ecs/terraform.tfvars.example new file mode 100644 index 0000000..8ec5638 --- /dev/null +++ b/modules/aws-ecs/terraform.tfvars.example @@ -0,0 +1,24 @@ +region = "us-east-1" +cluster_name = "oba-cluster" +container_name = "onebusaway-api-server" +container_image = "ghcr.io/onebusaway/onebusaway-api-webapp:latest" +container_cpu = 2048 +container_memory = 4096 +log_group_name = "/ecs/oba-container-logs" +service_name = "oba-service" + +env_var_tz = "America/Toronto" +env_var_gtfs_url = "https://api.cityofkingston.ca/gtfs/gtfs.zip" +env_var_vehicle_positions_url = "https://api.cityofkingston.ca/gtfs-realtime/vehicleupdates.pb" +env_var_trip_updates_url = "https://api.cityofkingston.ca/gtfs-realtime/tripupdates.pb" +env_var_alerts_url = "https://api.cityofkingston.ca/gtfs-realtime/alerts.pb" +env_var_feed_api_key = "" +env_var_feed_api_value = "" +env_var_refresh_interval = "30" +env_var_agency_id = "0" +env_var_jdbc_user = "oba_user" +env_var_jdbc_password = "oba_password" +env_var_jdbc_url = "jdbc:mysql://:/oba_database" +env_var_google_maps_api_key = "" +env_var_google_maps_channel_id = "" +env_var_google_maps_client_id = "" diff --git a/modules/aws-ecs/variables.tf b/modules/aws-ecs/variables.tf new file mode 100644 index 0000000..6443c5f --- /dev/null +++ b/modules/aws-ecs/variables.tf @@ -0,0 +1,116 @@ +variable "region" { + description = "The AWS region to deploy to" + type = string +} + +variable "cluster_name" { + description = "The name of the ECS cluster" + type = string +} + +variable "container_name" { + description = "The name of the container" + type = string +} + +variable "container_image" { + description = "Docker image for the container, we use github container registry here to avoid rate limiting in docker hub, see: https://medium.com/@alaa.barqawi/docker-rate-limit-with-azure-container-instance-and-aks-4449cede66dd" + type = string +} + +variable "container_cpu" { + description = "The number of CPU units for the container(1 vCPU = 1024 CPU units)" + type = number +} + +variable "container_memory" { + description = "The amount of memory for the container(in MiB)" + type = number +} + +variable "log_group_name" { + description = "The name of the log group for container logs" + type = string +} + +variable "service_name" { + description = "The name of the ECS service" + type = string +} + + +variable "env_var_tz" { + description = "Environment variable TZ" + type = string +} + +variable "env_var_gtfs_url" { + description = "Environment variable GTFS_URL" + type = string +} + +variable "env_var_vehicle_positions_url" { + description = "Environment variable VEHICLE_POSITIONS_URL" + type = string +} + +variable "env_var_trip_updates_url" { + description = "Environment variable TRIP_UPDATES_URL" + type = string +} + +variable "env_var_alerts_url" { + description = "Environment variable ALERTS_URL" + type = string +} + +variable "env_var_feed_api_key" { + description = "Environment variable FEED_API_KEY" + type = string +} + +variable "env_var_feed_api_value" { + description = "Environment variable FEED_API_VALUE" + type = string +} + +variable "env_var_refresh_interval" { + description = "Environment variable REFRESH_INTERVAL" + type = string +} + +variable "env_var_agency_id" { + description = "Environment variable AGENCY_ID" + type = string +} + +variable "env_var_jdbc_user" { + description = "Environment variable JDBC_USER" + type = string +} + +variable "env_var_jdbc_password" { + description = "Environment variable JDBC_PASSWORD" + type = string +} + +variable "env_var_jdbc_url" { + description = "Environment variable JDBC_URL" + type = string +} + +variable "env_var_google_maps_api_key" { + description = "Environment variable GOOGLE_MAPS_API_KEY" + type = string +} + +variable "env_var_google_maps_channel_id" { + description = "Environment variable GOOGLE_MAPS_CHANNEL_ID" + type = string +} + +variable "env_var_google_maps_client_id" { + description = "Environment variable GOOGLE_MAPS_CLIENT_ID" + type = string +} + diff --git a/modules/azure-aci/.terraform.lock.hcl b/modules/azure-aci/.terraform.lock.hcl new file mode 100644 index 0000000..dd2a758 --- /dev/null +++ b/modules/azure-aci/.terraform.lock.hcl @@ -0,0 +1,20 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/azurerm" { + version = "3.111.0" + hashes = [ + "h1:e44vPg88+i3UazBUgkSfqnzvLvW/BqKq4FGLgKiFoqQ=", + "h1:oIDvav/uHpeCyQHiEsC/TMzelxJ5Rf8vKQOnp0lcUfM=", + "zh:42aabdcbfa6ed995068b90e1e683bfd9ba73a9d3581d22cd91fa432680273beb", + "zh:506210b1b22e35d8f2cb06b23198fa853114c9c93210d2893ce39d743942d398", + "zh:58e80aedb41a9e1236e9eb6a06a8436ef7ce7a59ff0616b01cbc18cbd18e7f23", + "zh:68a5ea919a2c04237b7ae773f9fd251cd8e501e433847962bd417c834eb81682", + "zh:6a6a905237c58b930dfaff081bb8ffd6553c3da90a863f31f88c9e4f7f2ad899", + "zh:aac8d550115f511f5e1d38881c6a350f9529980d8f94db1e5efe8cfd50d054b0", + "zh:ac5dfe428b5cc8e04ef5c6763bac5b9462b04b557e6343e423145369ed305ef9", + "zh:aca7b59f88f7b942bddc9e6c7e92302ee6c566ee8126c8ce521b81291e93ff3d", + "zh:d4131953594a19416abcefb859b81f674ab876bc6f0f53bd00c2c771c48dcf43", + "zh:e8126805196280390d1288f594b9dde271728e95301ac90703a44e3ec674864e", + ] +} diff --git a/modules/azure-aci/main.tf b/modules/azure-aci/main.tf new file mode 100644 index 0000000..5ce35a8 --- /dev/null +++ b/modules/azure-aci/main.tf @@ -0,0 +1,91 @@ +provider "azurerm" { + features {} +} + +locals { + liveness_probe_path = "/onebusaway-api-webapp/api/where/current-time.json?key=org.onebusaway.iphone" + liveness_probe_port = 8080 + liveness_probe_initial_delay_seconds = 120 + liveness_probe_period_seconds = 30 +} + +resource "azurerm_resource_group" "main" { + name = var.resource_group_name + location = var.location +} + +resource "azurerm_storage_account" "main" { + name = var.storage_account_name + resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.main.location + account_tier = "Standard" + account_replication_type = "LRS" + + # tags = var.tags +} + +resource "azurerm_storage_share" "main" { + name = var.storage_share_name + storage_account_name = azurerm_storage_account.main.name + quota = var.storage_share_quota + + depends_on = [ + azurerm_storage_account.main + ] +} + + +resource "azurerm_container_group" "main" { + name = var.container_group_name + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + os_type = "Linux" + + container { + name = var.container_name + image = var.container_image + cpu = var.container_cpu + memory = var.container_memory + + environment_variables = { + TZ = var.env_var_tz + GTFS_URL = var.env_var_gtfs_url + VEHICLE_POSITIONS_URL = var.env_var_vehicle_positions_url + TRIP_UPDATES_URL = var.env_var_trip_updates_url + ALERTS_URL = var.env_var_alerts_url + REFRESH_INTERVAL = var.env_var_refresh_interval + AGENCY_ID = var.env_var_agency_id + FEED_API_KEY = var.env_var_feed_api_key + FEED_API_VALUE = var.env_var_feed_api_value + JDBC_USER = var.env_var_jdbc_user + JDBC_PASSWORD = var.env_var_jdbc_password + JDBC_URL = var.env_var_jdbc_url + GOOGLE_MAPS_API_KEY = var.env_var_google_maps_api_key + GOOGLE_MAPS_CHANNEL_ID = var.env_var_google_maps_channel_id + GOOGLE_MAPS_CLIENT_ID = var.env_var_google_maps_client_id + } + + ports { + port = "8080" + protocol = "TCP" + } + + volume { + name = "bundle" + mount_path = "/bundle" + read_only = false + share_name = azurerm_storage_share.main.name + storage_account_name = azurerm_storage_account.main.name + storage_account_key = azurerm_storage_account.main.primary_access_key + } + + liveness_probe { + http_get { + path = local.liveness_probe_path + port = local.liveness_probe_port + } + initial_delay_seconds = local.liveness_probe_initial_delay_seconds + period_seconds = local.liveness_probe_period_seconds + } + } +} diff --git a/modules/azure-aci/output.tf b/modules/azure-aci/output.tf new file mode 100644 index 0000000..14fbe5c --- /dev/null +++ b/modules/azure-aci/output.tf @@ -0,0 +1,3 @@ +output "container_ipv4_address" { + value = azurerm_container_group.main.ip_address +} \ No newline at end of file diff --git a/modules/azure-aci/readme.md b/modules/azure-aci/readme.md new file mode 100644 index 0000000..da69617 --- /dev/null +++ b/modules/azure-aci/readme.md @@ -0,0 +1,69 @@ +# Deployment Guide for Azure Container Instances + +Azure Container Instances (ACI) is an excellent choice for deploying the OneBusAway server, providing a fast and straightforward way to run containers in Azure without managing virtual machines. This guide will walk you through deploying the OneBusAway server on Azure Container Instances using Opentofu. + +## Prerequisites + +1. An Azure account. If you don't have one, you can create a free account [here](https://azure.microsoft.com/en-us/free/). + +2. Azure CLI. You can install it by following the instructions [here](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). + +3. Opentofu, an open-source Terraform alternative. You can install it by following the instructions [here](https://opentofu.org/docs/intro/install/). + +4. Ensure you have *ALL* the prerequisites installed before starting the deployment. + +## Steps + +1. Clone this repository to your local machine. You can run: + +```bash +git clone https://github.com/OneBusAway/onebusaway-deployment.git +cd onebusaway-deployment/modules/azure-aci +``` + +2. Initialize the project. This will download the necessary plugins and providers for the project: + +```bash +tofu init +``` + +3. Create a `terraform.tfvars` file by copying the example variables file, and then modify it according to your needs: + +```bash +cp terraform.tfvars.example terraform.tfvars +``` + +4. Edit the `terraform.tfvars` file and update the variable values to match your specific requirements, such as Azure region, resource group name, container details, and environment variables. + + +5. Run Tofu plan to preview the infrastructure changes: + +```bash +tofu plan +``` + +6. Apply the Tofu configuration to create the actual resources: + +```bash +tofu apply +``` + +Type `yes` when prompted to confirm the resource creation. + +7. After the deployment is complete, verify the created resources in the Azure Portal. Ensure the container group, storage account, file share, and other related resources are created and running correctly. + +8. Access the OneBusAway server by visiting the public IP of the container instance. You can find the server IP in the Azure Portal under the container group details. + +## Clean up + +If you want to shut down the server and clean up the resources, you can run the following command: + +```bash +tofu destroy +``` + +Opentofu will destroy all resources created by this project, including the container group, storage account, file share, and other resources. + +## Conclusion + +This guide shows you how to deploy the OneBusAway server on Azure Container Instances using Opentofu. If you have any questions or suggestions, feel free to open an issue in this repository. \ No newline at end of file diff --git a/modules/azure-aci/terraform.tfvars.example b/modules/azure-aci/terraform.tfvars.example new file mode 100644 index 0000000..5b5af36 --- /dev/null +++ b/modules/azure-aci/terraform.tfvars.example @@ -0,0 +1,26 @@ +resource_group_name = "oba-resources" +location = "East US" +container_group_name = "oba_container_group" +container_name = "onebusaway-api-server" +container_image = "ghcr.io/onebusaway/onebusaway-api-webapp:latest" +container_cpu = 2 +container_memory = 4 +storage_account_name = "obaacistorageaccount" +storage_share_name = "bundle" +storage_share_quota = 1 + +env_var_tz = "America/Toronto" +env_var_gtfs_url = "https://api.cityofkingston.ca/gtfs/gtfs.zip" +env_var_vehicle_positions_url = "https://api.cityofkingston.ca/gtfs-realtime/vehicleupdates.pb" +env_var_trip_updates_url = "https://api.cityofkingston.ca/gtfs-realtime/tripupdates.pb" +env_var_alerts_url = "https://api.cityofkingston.ca/gtfs-realtime/alerts.pb" +env_var_feed_api_key = "" +env_var_feed_api_value = "" +env_var_refresh_interval = "30" +env_var_agency_id = "0" +env_var_jdbc_user = "oba_user" +env_var_jdbc_password = "oba_password" +env_var_jdbc_url = "jdbc:mysql://:/oba_database" +env_var_google_maps_api_key = "" +env_var_google_maps_channel_id = "" +env_var_google_maps_client_id = "" diff --git a/modules/azure-aci/variables.tf b/modules/azure-aci/variables.tf new file mode 100644 index 0000000..727d02a --- /dev/null +++ b/modules/azure-aci/variables.tf @@ -0,0 +1,128 @@ +variable "resource_group_name" { + description = "The name of the resource group" + type = string +} + +variable "location" { + description = "The location of the resources" + type = string +} + +variable "container_group_name" { + description = "The name of the container group" + type = string +} + +variable "container_name" { + description = "The name of the container" + type = string +} + +variable "container_image" { + description = "Docker image for the container" + type = string +} + +variable "container_cpu" { + description = "The number of CPU units for the container" + type = number +} + +variable "container_memory" { + description = "The amount of memory for the container" + type = number +} + +variable "storage_account_name" { + description = "The name of the storage account" + type = string +} + +variable "storage_share_name" { + description = "The name of the storage share" + type = string +} + +variable "storage_share_quota" { + + description = "The quota for the storage share, in GB" + type = number +} + +variable "env_var_tz" { + description = "Environment variable TZ" + type = string +} + +variable "env_var_gtfs_url" { + description = "Environment variable GTFS_URL" + type = string +} + +variable "env_var_vehicle_positions_url" { + description = "Environment variable VEHICLE_POSITIONS_URL" + type = string +} + +variable "env_var_trip_updates_url" { + description = "Environment variable TRIP_UPDATES_URL" + type = string +} + +variable "env_var_alerts_url" { + description = "Environment variable ALERTS_URL" + type = string +} + +variable "env_var_feed_api_key" { + description = "Environment variable FEED_API_KEY" + type = string +} + +variable "env_var_feed_api_value" { + description = "Environment variable FEED_API_VALUE" + type = string +} + +variable "env_var_refresh_interval" { + description = "Environment variable REFRESH_INTERVAL" + type = string +} + +variable "env_var_agency_id" { + description = "Environment variable AGENCY_ID" + type = string +} + +variable "env_var_jdbc_user" { + description = "Environment variable JDBC_USER" + type = string +} + +variable "env_var_jdbc_password" { + description = "Environment variable JDBC_PASSWORD" + type = string +} + +variable "env_var_jdbc_url" { + description = "Environment variable JDBC_URL" + type = string +} + +variable "env_var_google_maps_api_key" { + description = "Environment variable GOOGLE_MAPS_API_KEY" + type = string +} + +variable "env_var_google_maps_channel_id" { + description = "Environment variable GOOGLE_MAPS_CHANNEL_ID" + type = string +} + +variable "env_var_google_maps_client_id" { + description = "Environment variable GOOGLE_MAPS_CLIENT_ID" + type = string +} + + + diff --git a/modules/gcp-cr/.terraform.lock.hcl b/modules/gcp-cr/.terraform.lock.hcl new file mode 100644 index 0000000..cd8a041 --- /dev/null +++ b/modules/gcp-cr/.terraform.lock.hcl @@ -0,0 +1,19 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/google" { + version = "5.38.0" + hashes = [ + "h1:qwXFzfVXOTUnzVGys1/tXjEPKlz1TbssMmG1HDELNiA=", + "zh:234832f2795dc3cb868e09999dee02caeed62c8069e80ae1249368c4f9edf629", + "zh:2c8e00ddcb9ec498f58c72e925a1c041233d7b3ebac8535902edad8e3ec5b2d8", + "zh:52526913246417d9223879a32cd72bbbf47f4dbfd05e89cffc4f22106feb81ae", + "zh:65172fc8334126ed065fd2a8364436decf07b75d1347395cc8a1f2d4a628ca02", + "zh:781bb362726a51b98b1fb0b8379a9293bf7415adb750c1284e074788465f9cdd", + "zh:8866dc2d5249a1f90a1e26462451e264c1358939d2e8313bd73260f3d407eb3a", + "zh:9a63de80fc8724b9fb9bd0fd88449cadd60ce3081c763a393e0ac0bd1edb9cb2", + "zh:c73a2608be1a78bd02acca450b55ae4de01d29d029504ba92434159672932aea", + "zh:d7b68aab00f5cf9424df9db0cbf8d6d2efde8188206938a22a11b2b569806095", + "zh:e820d998be11b7ea2ff86391733d434f23846386f53237d19253c2af9197edb1", + ] +} diff --git a/modules/gcp-cr/main.tf b/modules/gcp-cr/main.tf new file mode 100644 index 0000000..530b3ca --- /dev/null +++ b/modules/gcp-cr/main.tf @@ -0,0 +1,106 @@ +provider "google" { + project = var.project_id + region = var.region +} + +resource "google_cloud_run_v2_service" "main" { + name = var.service_name + location = var.region + + template { + scaling { + max_instance_count = var.max_instance_count + } + + volumes { + name = "bundle" + } + + containers { + image = var.container_image + + volume_mounts { + name = "bundle" + mount_path = "/bundle" + } + + resources { + limits = { + memory = "4Gi" + cpu = "2" + } + } + + env { + name = "TZ" + value = var.env_var_tz + } + env { + name = "GTFS_URL" + value = var.env_var_gtfs_url + } + env { + name = "VEHICLE_POSITIONS_URL" + value = var.env_var_vehicle_positions_url + } + env { + name = "TRIP_UPDATES_URL" + value = var.env_var_trip_updates_url + } + env { + name = "ALERTS_URL" + value = var.env_var_alerts_url + } + env { + name = "FEED_API_KEY" + value = var.env_var_feed_api_key + } + env { + name = "FEED_API_VALUE" + value = var.env_var_feed_api_value + } + env { + name = "REFRESH_INTERVAL" + value = var.env_var_refresh_interval + } + env { + name = "AGENCY_ID" + value = var.env_var_agency_id + } + env { + name = "JDBC_USER" + value = var.env_var_jdbc_user + } + env { + name = "JDBC_PASSWORD" + value = var.env_var_jdbc_password + } + env { + name = "JDBC_URL" + value = var.env_var_jdbc_url + } + env { + name = "GOOGLE_MAPS_API_KEY" + value = var.env_var_google_maps_api_key + } + env { + name = "GOOGLE_MAPS_CHANNEL_ID" + value = var.env_var_google_maps_channel_id + } + env { + name = "GOOGLE_MAPS_CLIENT_ID" + value = var.env_var_google_maps_client_id + } + } + } +} + +# Allow all users to access the service, since it's a public API +resource "google_cloud_run_v2_service_iam_binding" "noauth" { + name = google_cloud_run_v2_service.main.name + location = google_cloud_run_v2_service.main.location + + + role = "roles/run.invoker" + members = ["allUsers"] +} diff --git a/modules/gcp-cr/output.tf b/modules/gcp-cr/output.tf new file mode 100644 index 0000000..e112297 --- /dev/null +++ b/modules/gcp-cr/output.tf @@ -0,0 +1,3 @@ +output "url" { + value = google_cloud_run_v2_service.main.uri +} diff --git a/modules/gcp-cr/readme.md b/modules/gcp-cr/readme.md new file mode 100644 index 0000000..badf47f --- /dev/null +++ b/modules/gcp-cr/readme.md @@ -0,0 +1,68 @@ +# Deployment Guide for Google Cloud Run + +Google Cloud Run is a fully managed environment for running containerized applications. This guide will walk you through deploying the OneBusAway server on Google Cloud Run using Opentofu. + +## Prerequisites + +1. A Google Cloud Platform (GCP) account. If you don't have one, you can create a free account [here](https://cloud.google.com/free). + +2. Google Cloud SDK (gcloud). You can install it by following the instructions [here](https://cloud.google.com/sdk/docs/install). + +3. Opentofu, an open-source Terraform alternative. You can install it by following the instructions [here](https://opentofu.org/docs/intro/install/). + +4. Ensure you have *ALL* the prerequisites installed before starting the deployment. + +## Steps + +1. Clone this repository to your local machine. You can run: + +```bash +git clone https://github.com/OneBusAway/onebusaway-deployment.git +cd onebusaway-deployment/modules/gcp-cr +``` + +2. Initialize the project. This will download the necessary plugins and providers for the project: + +```bash +tofu init +``` + +3. Create a `terraform.tfvars` file by copying the example variables file, and then modify it according to your needs: + +```bash +cp terraform.tfvars.example terraform.tfvars +``` + +4. Edit the `terraform.tfvars` file and update the variable values to match your specific requirements, such as GCP project ID, region, service name, container details, and environment variables. + +5. Run Tofu plan to preview the infrastructure changes: + +```bash +tofu plan +``` + +6. Apply the Tofu configuration to create the actual resources: + +```bash +tofu apply +``` + +Type `yes` when prompted to confirm the resource creation. + +7. After the deployment is complete, verify the created resources in the Google Cloud Console. Ensure the Cloud Run service, IAM binding, and other related resources are created and running correctly. + +8. Access the OneBusAway server by visiting the public URL of the Cloud Run service. You can find the service URL in the Google Cloud Console under the Cloud Run service details. + +## Clean up + +If you want to shut down the server and clean up the resources, you can run the following command: + +```bash +tofu destroy +``` + +Opentofu will destroy all resources created by this project, including the Cloud Run service and IAM bindings. + +## Conclusion + +This guide shows you how to deploy the OneBusAway server on Google Cloud Run using Opentofu. If you have any questions or suggestions, feel free to open an issue in this repository. \ No newline at end of file diff --git a/modules/gcp-cr/terraform.tfvars.example b/modules/gcp-cr/terraform.tfvars.example new file mode 100644 index 0000000..6ce992b --- /dev/null +++ b/modules/gcp-cr/terraform.tfvars.example @@ -0,0 +1,21 @@ +project_id = "your-gcp-project-id" +max_instance_count = 1 +region = "us-central1" +service_name = "onebusaway-api" +container_image = "opentransitsoftwarefoundation/onebusaway-api-webapp:2.5.12-cs-v1.0.0" + +env_var_tz = "America/Toronto" +env_var_gtfs_url = "https://api.cityofkingston.ca/gtfs/gtfs.zip" +env_var_vehicle_positions_url = "https://api.cityofkingston.ca/gtfs-realtime/vehicleupdates.pb" +env_var_trip_updates_url = "https://api.cityofkingston.ca/gtfs-realtime/tripupdates.pb" +env_var_alerts_url = "https://api.cityofkingston.ca/gtfs-realtime/alerts.pb" +env_var_feed_api_key = "" +env_var_feed_api_value = "" +env_var_refresh_interval = "30" +env_var_agency_id = "0" +env_var_jdbc_user = "oba_user" +env_var_jdbc_password = "oba_password" +env_var_jdbc_url = "jdbc:mysql://:/oba_database" +env_var_google_maps_api_key = "" +env_var_google_maps_channel_id = "" +env_var_google_maps_client_id = "" diff --git a/modules/gcp-cr/variables.tf b/modules/gcp-cr/variables.tf new file mode 100644 index 0000000..f8dd2c1 --- /dev/null +++ b/modules/gcp-cr/variables.tf @@ -0,0 +1,118 @@ +variable "project_id" { + description = "The ID of the project in which to create the resources." + type = string +} + +variable "max_instance_count" { + description = "The maximum number of instances that the service should scale up to." + type = number + default = 1 +} + +variable "region" { + description = "The region of the resources." + type = string + default = "us-central1" +} + +variable "service_name" { + description = "The name of the Cloud Run service." + type = string + default = "onebusaway-api" +} + +variable "container_image" { + description = "Docker image for the container, expected an image path like [host/]repo-path[:tag and/or @digest], where host is one of [region.]gcr.io, [region-]docker.pkg.dev or docker.io" + type = string + default = "opentransitsoftwarefoundation/onebusaway-api-webapp:2.5.12-cs-v1.0.0" +} + +variable "env_var_tz" { + description = "Environment variable TZ" + type = string + default = "America/Toronto" +} + +variable "env_var_gtfs_url" { + description = "Environment variable GTFS_URL" + type = string + default = "https://api.cityofkingston.ca/gtfs/gtfs.zip" +} + +variable "env_var_vehicle_positions_url" { + description = "Environment variable VEHICLE_POSITIONS_URL" + type = string + default = "https://api.cityofkingston.ca/gtfs-realtime/vehicleupdates.pb" +} + +variable "env_var_trip_updates_url" { + description = "Environment variable TRIP_UPDATES_URL" + type = string + default = "https://api.cityofkingston.ca/gtfs-realtime/tripupdates.pb" +} + +variable "env_var_alerts_url" { + description = "Environment variable ALERTS_URL" + type = string + default = "https://api.cityofkingston.ca/gtfs-realtime/alerts.pb" +} + +variable "env_var_feed_api_key" { + description = "Environment variable FEED_API_KEY" + type = string + default = "" +} + +variable "env_var_feed_api_value" { + description = "Environment variable FEED_API_VALUE" + type = string + default = "" +} + +variable "env_var_refresh_interval" { + description = "Environment variable REFRESH_INTERVAL" + type = string + default = "30" +} + +variable "env_var_agency_id" { + description = "Environment variable AGENCY_ID" + type = string + default = "0" +} + +variable "env_var_jdbc_user" { + description = "Environment variable JDBC_USER" + type = string + default = "oba_user" +} + +variable "env_var_jdbc_password" { + description = "Environment variable JDBC_PASSWORD" + type = string + default = "oba_password" +} + +variable "env_var_jdbc_url" { + description = "Environment variable JDBC_URL" + type = string + default = "jdbc:mysql://:/oba_database" +} + +variable "env_var_google_maps_api_key" { + description = "Environment variable GOOGLE_MAPS_API_KEY" + type = string + default = "" +} + +variable "env_var_google_maps_channel_id" { + description = "Environment variable GOOGLE_MAPS_CHANNEL_ID" + type = string + default = "" +} + +variable "env_var_google_maps_client_id" { + description = "Environment variable GOOGLE_MAPS_CLIENT_ID" + type = string + default = "" +} From a3f9e59ae9e4e325bf871cd06916f3593a42e594 Mon Sep 17 00:00:00 2001 From: Altonhe Date: Fri, 26 Jul 2024 20:53:08 -0400 Subject: [PATCH 2/2] fix lint --- modules/aws-ecs/main.tf | 1 - modules/aws-ecs/terraform.tfvars.example | 1 - modules/aws-ecs/variables.tf | 5 ----- 3 files changed, 7 deletions(-) diff --git a/modules/aws-ecs/main.tf b/modules/aws-ecs/main.tf index d164db4..ceea091 100644 --- a/modules/aws-ecs/main.tf +++ b/modules/aws-ecs/main.tf @@ -4,7 +4,6 @@ provider "aws" { locals { liveness_probe_path = "/onebusaway-api-webapp/api/where/current-time.json?key=org.onebusaway.iphone" - liveness_probe_port = 8080 liveness_probe_initial_delay_seconds = 120 liveness_probe_period_seconds = 30 } diff --git a/modules/aws-ecs/terraform.tfvars.example b/modules/aws-ecs/terraform.tfvars.example index 8ec5638..f9934db 100644 --- a/modules/aws-ecs/terraform.tfvars.example +++ b/modules/aws-ecs/terraform.tfvars.example @@ -4,7 +4,6 @@ container_name = "onebusaway-api-server" container_image = "ghcr.io/onebusaway/onebusaway-api-webapp:latest" container_cpu = 2048 container_memory = 4096 -log_group_name = "/ecs/oba-container-logs" service_name = "oba-service" env_var_tz = "America/Toronto" diff --git a/modules/aws-ecs/variables.tf b/modules/aws-ecs/variables.tf index 6443c5f..771b88c 100644 --- a/modules/aws-ecs/variables.tf +++ b/modules/aws-ecs/variables.tf @@ -28,11 +28,6 @@ variable "container_memory" { type = number } -variable "log_group_name" { - description = "The name of the log group for container logs" - type = string -} - variable "service_name" { description = "The name of the ECS service" type = string