infra/main.tf (147 lines of code) (raw):

/** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ locals { unique = "${var.deployment_name}-${random_id.default.hex}" application_image = "us-docker.pkg.dev/hsa-public/containers/cloud-client-api/${lower(var.language)}:${var.image_version}" } resource "random_id" "default" { byte_length = 2 } ####################################################################################### # APIs module "project_services" { source = "terraform-google-modules/project-factory/google//modules/project_services" version = "~> 18.0" disable_services_on_destroy = false project_id = var.project_id activate_apis = [ "run.googleapis.com", ] } ####################################################################################### # Cloud Storage resource "google_storage_bucket" "processed_data" { project = var.project_id name = "processed-${local.unique}-${var.project_id}" location = var.region storage_class = "REGIONAL" labels = var.labels force_destroy = true } resource "google_storage_bucket" "raw_data" { project = var.project_id name = "raw_data-${local.unique}-${var.project_id}" location = var.region storage_class = "REGIONAL" labels = var.labels force_destroy = true } resource "google_storage_bucket_object" "default" { bucket = google_storage_bucket.raw_data.name name = "squirrels.csv" source = "${path.module}/data/squirrels.csv" } ####################################################################################### # Cloud Run Service resource "google_cloud_run_v2_service" "default" { project = var.project_id name = "chart-${local.unique}" location = var.region deletion_protection = false labels = var.labels template { service_account = google_service_account.reader.email containers { image = local.application_image env { name = "PROCESSED_DATA_BUCKET" value = google_storage_bucket.processed_data.name } } } depends_on = [module.project_services] } resource "google_cloud_run_v2_service_iam_member" "public" { project = google_cloud_run_v2_service.default.project location = google_cloud_run_v2_service.default.location name = google_cloud_run_v2_service.default.name role = "roles/run.invoker" member = "allUsers" } ####################################################################################### # Cloud Run Job resource "google_cloud_run_v2_job" "default" { project = var.project_id name = "process-${local.unique}" location = var.region labels = var.labels deletion_protection = false template { template { service_account = google_service_account.writer.email containers { image = local.application_image command = ["process"] env { name = "RAW_DATA_BUCKET" value = google_storage_bucket.raw_data.name } env { name = "PROCESSED_DATA_BUCKET" value = google_storage_bucket.processed_data.name } } } } depends_on = [module.project_services] } ####################################################################################### # Service account - Data Writer resource "google_service_account" "writer" { project = var.project_id account_id = "write-${local.unique}" display_name = "SA with write access to Cloud Storage" } // Client APIs need to get the bucket to then get the object. resource "google_project_iam_custom_role" "object_downloader" { project = var.project_id role_id = "objectDownloader_${random_id.default.hex}" title = "Cloud Storage Object Downloader" description = "Permissions to download an object from a Cloud Storage bucket" permissions = ["storage.objects.get", "storage.objects.list", "storage.buckets.get"] } resource "google_storage_bucket_iam_member" "writer_raw_data" { bucket = google_storage_bucket.raw_data.name role = google_project_iam_custom_role.object_downloader.id member = "serviceAccount:${google_service_account.writer.email}" depends_on = [google_cloud_run_v2_service.default] # IAM eventual consistency buffer } resource "google_storage_bucket_iam_member" "writer_processed_data" { bucket = google_storage_bucket.processed_data.name role = "roles/storage.admin" member = "serviceAccount:${google_service_account.writer.email}" } resource "google_project_iam_member" "writer_logging" { project = var.project_id role = "roles/logging.logWriter" member = "serviceAccount:${google_service_account.writer.email}" } ####################################################################################### # Service account - Read-only resource "google_service_account" "reader" { project = var.project_id account_id = "read-${local.unique}" display_name = "SA with read-only access access to Cloud Storage" } resource "google_storage_bucket_iam_member" "reader_processed_data" { bucket = google_storage_bucket.processed_data.name role = google_project_iam_custom_role.object_downloader.id member = "serviceAccount:${google_service_account.reader.email}" depends_on = [google_cloud_run_v2_service.default] # IAM eventual consistency buffer } resource "google_project_iam_member" "reader_logging" { project = var.project_id role = "roles/logging.logWriter" member = "serviceAccount:${google_service_account.reader.email}" }