main.tf (209 lines of code) (raw):
/**
* Copyright 2023 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.
*/
module "project_services" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 18.0"
disable_services_on_destroy = var.disable_services_on_destroy
project_id = var.project_id
activate_apis = [
"aiplatform.googleapis.com",
"artifactregistry.googleapis.com",
"bigquery.googleapis.com",
"cloudbuild.googleapis.com",
"cloudfunctions.googleapis.com",
"cloudresourcemanager.googleapis.com",
"compute.googleapis.com",
"config.googleapis.com",
"documentai.googleapis.com",
"eventarc.googleapis.com",
"iam.googleapis.com",
"run.googleapis.com",
"serviceusage.googleapis.com",
"storage-api.googleapis.com",
"storage.googleapis.com",
]
}
resource "random_id" "unique_id" {
byte_length = 3
}
locals {
bucket_main_name = var.unique_names ? "summary-main-${var.project_id}-${random_id.unique_id.hex}" : "summary-main-${var.project_id}"
bucket_docs_name = var.unique_names ? "summary-docs-${var.project_id}-${random_id.unique_id.hex}" : "summary-docs-${var.project_id}"
webhook_name = var.unique_names ? "summary-webhook-${random_id.unique_id.hex}" : "summary-webhook"
webhook_sa_name = var.unique_names ? "summary-webhook-sa-${random_id.unique_id.hex}" : "summary-webhook-sa"
artifact_repo_name = var.unique_names ? "summary-artifact-repo-${random_id.unique_id.hex}" : "summary-artifact-repo"
trigger_name = var.unique_names ? "summary-trigger-${random_id.unique_id.hex}" : "summary-trigger"
trigger_sa_name = var.unique_names ? "summary-trigger-sa-${random_id.unique_id.hex}" : "summary-trigger-sa"
ocr_processor_name = var.unique_names ? "summary-ocr-processor-${random_id.unique_id.hex}" : "summary-ocr-processor"
bq_dataset_name = var.unique_names ? "summary_dataset_${random_id.unique_id.hex}" : "summary_dataset"
}
#-- Cloud Storage buckets --#
resource "google_storage_bucket" "main" {
project = module.project_services.project_id
name = local.bucket_main_name
location = var.region
force_destroy = true
uniform_bucket_level_access = true
labels = var.labels
}
resource "google_storage_bucket" "docs" {
project = module.project_services.project_id
name = local.bucket_docs_name
location = var.region
force_destroy = true
uniform_bucket_level_access = true
labels = var.labels
}
#-- Cloud Function webhook --#
resource "google_cloudfunctions2_function" "webhook" {
project = module.project_services.project_id
name = local.webhook_name
location = var.region
labels = var.labels
build_config {
runtime = "python312"
entry_point = "on_cloud_event"
docker_repository = google_artifact_registry_repository.webhook_images.id
source {
storage_source {
bucket = google_storage_bucket.main.name
object = google_storage_bucket_object.webhook_staging.name
}
}
}
service_config {
available_memory = "1G"
service_account_email = google_service_account.webhook.email
environment_variables = {
PROJECT_ID = module.project_services.project_id
LOCATION = var.region
OUTPUT_BUCKET = google_storage_bucket.main.name
DOCAI_PROCESSOR = google_document_ai_processor.ocr.id
DOCAI_LOCATION = google_document_ai_processor.ocr.location
BQ_DATASET = google_bigquery_dataset.main.dataset_id
BQ_TABLE = google_bigquery_table.main.table_id
LOG_EXECUTION_ID = true
}
}
}
resource "google_project_iam_member" "webhook" {
project = module.project_services.project_id
member = google_service_account.webhook.member
for_each = toset([
"roles/aiplatform.serviceAgent", # https://cloud.google.com/iam/docs/service-agents
"roles/bigquery.dataEditor", # https://cloud.google.com/bigquery/docs/access-control
"roles/documentai.apiUser", # https://cloud.google.com/document-ai/docs/access-control/iam-roles
])
role = each.key
}
resource "google_service_account" "webhook" {
project = module.project_services.project_id
account_id = local.webhook_sa_name
display_name = "Doc summary webhook"
}
resource "google_artifact_registry_repository" "webhook_images" {
project = module.project_services.project_id
location = var.region
repository_id = local.artifact_repo_name
format = "DOCKER"
labels = var.labels
}
data "archive_file" "webhook_staging" {
type = "zip"
source_dir = abspath("${path.module}/webhook")
output_path = abspath("${path.module}/.tmp/webhook.zip")
excludes = [
".mypy_cache",
".pytest_cache",
".ruff_cache",
"__pycache__",
"env",
]
}
resource "google_storage_bucket_object" "webhook_staging" {
name = "webhook-staging/${data.archive_file.webhook_staging.output_base64sha256}.zip"
bucket = google_storage_bucket.main.name
source = data.archive_file.webhook_staging.output_path
}
#-- Eventarc trigger --#
resource "google_eventarc_trigger" "trigger" {
project = module.project_services.project_id
location = var.region
name = local.trigger_name
service_account = google_service_account.trigger.email
labels = var.labels
matching_criteria {
attribute = "type"
value = "google.cloud.storage.object.v1.finalized"
}
matching_criteria {
attribute = "bucket"
value = google_storage_bucket.docs.name
}
destination {
cloud_run_service {
service = google_cloudfunctions2_function.webhook.name
region = var.region
}
}
}
resource "google_project_iam_member" "trigger" {
project = module.project_services.project_id
member = google_service_account.trigger.member
for_each = toset([
"roles/eventarc.eventReceiver", # https://cloud.google.com/eventarc/docs/access-control
"roles/run.invoker", # https://cloud.google.com/run/docs/reference/iam/roles
])
role = each.key
}
resource "google_service_account" "trigger" {
project = module.project_services.project_id
account_id = local.trigger_sa_name
display_name = "Doc summary Eventarc trigger"
}
#-- Cloud Storage Eventarc agent --#
resource "google_project_iam_member" "gcs_account" {
project = module.project_services.project_id
member = "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"
role = "roles/pubsub.publisher" # https://cloud.google.com/pubsub/docs/access-control
}
data "google_storage_project_service_account" "gcs_account" {
project = module.project_services.project_id
}
resource "google_project_iam_member" "eventarc_agent" {
project = module.project_services.project_id
member = "serviceAccount:${google_project_service_identity.eventarc_agent.email}"
role = "roles/eventarc.serviceAgent" # https://cloud.google.com/iam/docs/service-agents
}
resource "google_project_service_identity" "eventarc_agent" {
provider = google-beta
project = module.project_services.project_id
service = "eventarc.googleapis.com"
}
#-- Document AI --#
resource "google_document_ai_processor" "ocr" {
project = module.project_services.project_id
location = var.documentai_location
display_name = local.ocr_processor_name
type = "OCR_PROCESSOR"
}
#-- BigQuery --#
resource "google_bigquery_dataset" "main" {
project = module.project_services.project_id
dataset_id = local.bq_dataset_name
delete_contents_on_destroy = true
}
resource "google_bigquery_table" "main" {
project = module.project_services.project_id
dataset_id = google_bigquery_dataset.main.dataset_id
table_id = "summaries"
schema = file("${path.module}/schema.json")
deletion_protection = false
}