cloud-run-django-terraform/main.tf (189 lines of code) (raw):

# Step 1: Activate Google Cloud terraform { required_providers { google = { source = "hashicorp/google" version = "~> 3.66" } } } # Step 2: Set up variables provider "google" { project = var.project region = var.region } data "google_project" "project" { project_id = var.project } variable "project" { type = string description = "Google Cloud Project ID" } variable "region" { type = string default = "us-central1" description = "Google Cloud Region" } variable "service" { type = string default = "gametracker" description = "The name of the service" } # Step 3: Activate service APIs resource "google_project_service" "run" { service = "run.googleapis.com" disable_on_destroy = false } resource "google_project_service" "sql-component" { service = "sql-component.googleapis.com" disable_on_destroy = false } resource "google_project_service" "sqladmin" { service = "sqladmin.googleapis.com" disable_on_destroy = false } resource "google_project_service" "compute" { service = "compute.googleapis.com" disable_on_destroy = false } resource "google_project_service" "cloudbuild" { service = "cloudbuild.googleapis.com" disable_on_destroy = false } resource "google_project_service" "secretmanager" { service = "secretmanager.googleapis.com" disable_on_destroy = false } # Step 4: Create a custom Service Account resource "google_service_account" "django" { account_id = "django" } # Step 5: Create the database resource "random_password" "database_password" { length = 32 special = false } resource "google_sql_database_instance" "instance" { name = "gametracker" database_version = "POSTGRES_13" region = "us-central1" settings { tier = "db-f1-micro" } deletion_protection = true } resource "google_sql_database" "database" { name = "django" instance = google_sql_database_instance.instance.name } resource "google_sql_user" "django" { name = "django" instance = google_sql_database_instance.instance.name password = random_password.database_password.result } # Step 6: Create the secrets resource "google_storage_bucket" "media" { name = "${var.project}-images" location = "US" } resource "random_password" "django_secret_key" { special = false length = 50 } resource "google_secret_manager_secret" "django_settings" { secret_id = "django_settings" replication { automatic = true } depends_on = [google_project_service.secretmanager] } # Step 7: Prepare the secrets for Django resource "google_secret_manager_secret_version" "django_settings" { secret = google_secret_manager_secret.django_settings.id secret_data = templatefile("etc/env.tpl", { bucket = google_storage_bucket.media.name secret_key = random_password.django_secret_key.result user = google_sql_user.django instance = google_sql_database_instance.instance database = google_sql_database.database }) } # Step 8: Expand Service Account permissions resource "google_secret_manager_secret_iam_binding" "django_settings" { secret_id = google_secret_manager_secret.django_settings.id role = "roles/secretmanager.secretAccessor" members = [local.cloudbuild_serviceaccount, local.django_serviceaccount] } locals { cloudbuild_serviceaccount = "serviceAccount:${data.google_project.project.number}@cloudbuild.gserviceaccount.com" django_serviceaccount = "serviceAccount:${google_service_account.django.email}" } # Step 9: Populate secrets resource "random_password" "superuser_password" { length = 32 special = false } resource "google_secret_manager_secret" "superuser_password" { secret_id = "superuser_password" replication { automatic = true } depends_on = [google_project_service.secretmanager] } resource "google_secret_manager_secret_version" "superuser_password" { secret = google_secret_manager_secret.superuser_password.id secret_data = random_password.superuser_password.result } resource "google_secret_manager_secret_iam_binding" "superuser_password" { secret_id = google_secret_manager_secret.superuser_password.id role = "roles/secretmanager.secretAccessor" members = [local.cloudbuild_serviceaccount] } # Step 10: Create Cloud Run service resource "google_cloud_run_service" "service" { name = var.service location = var.region autogenerate_revision_name = true template { spec { service_account_name = google_service_account.django.email containers { image = "gcr.io/${var.project}/${var.service}" } } metadata { annotations = { "autoscaling.knative.dev/maxScale" = "100" "run.googleapis.com/cloudsql-instances" = google_sql_database_instance.instance.connection_name "run.googleapis.com/client-name" = "terraform" } } } traffic { percent = 100 latest_revision = true } } # Step 11: Specify Cloud Run permissions data "google_iam_policy" "noauth" { binding { role = "roles/run.invoker" members = [ "allUsers", ] } } resource "google_cloud_run_service_iam_policy" "noauth" { location = google_cloud_run_service.service.location project = google_cloud_run_service.service.project service = google_cloud_run_service.service.name policy_data = data.google_iam_policy.noauth.policy_data } # Step 12: Grant access to the database resource "google_project_iam_binding" "service_permissions" { for_each = toset([ "run.admin", "cloudsql.client" ]) role = "roles/${each.key}" members = [local.cloudbuild_serviceaccount, local.django_serviceaccount] } resource "google_service_account_iam_binding" "cloudbuild_sa" { service_account_id = google_service_account.django.name role = "roles/iam.serviceAccountUser" members = [local.cloudbuild_serviceaccount] } # Step 14: View final output output "superuser_password" { value = google_secret_manager_secret_version.superuser_password.secret_data sensitive = true } output "service_url" { value = google_cloud_run_service.service.status[0].url }