modules/genomics_dsub/main.tf (212 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. */ locals { random_id = var.deployment_id != null ? var.deployment_id : random_id.default.0.hex region = join("-", [split("-", var.zone)[0], split("-", var.zone)[1]]) project = (var.create_project ? try(module.project_radlab_genomics.0, null) : try(data.google_project.existing_project.0, null) ) network = ( var.create_network ? try(module.vpc_ngs.0.network.network, null) : try(data.google_compute_network.default.0, null) ) subnet = ( var.create_network ? try(module.vpc_ngs.0.subnets["${local.region}/${var.subnet}"], null) : try(data.google_compute_subnetwork.default.0, null) ) ngs_sa_project_roles = [ "roles/compute.instanceAdmin", "roles/storage.objectViewer", "roles/storage.admin", "roles/lifesciences.serviceAgent", "roles/lifesciences.workflowsRunner", "roles/iam.serviceAccountUser" ] default_apis = [ "compute.googleapis.com", "lifesciences.googleapis.com", "cloudfunctions.googleapis.com", "cloudbuild.googleapis.com" ] project_services = var.enable_services ? (var.billing_budget_pubsub_topic ? distinct(concat(local.default_apis,["pubsub.googleapis.com"])) : local.default_apis) : [] } resource "random_id" "default" { count = var.deployment_id == null ? 1 : 0 byte_length = 2 } ##################### # GENOMICS PROJECT # ##################### data "google_project" "existing_project" { count = var.create_project ? 0 : 1 project_id = var.project_id_prefix } module "project_radlab_genomics" { count = var.create_project ? 1 : 0 source = "terraform-google-modules/project-factory/google" version = "~> 13.0" name = format("%s-%s", var.project_id_prefix, local.random_id) random_project_id = false folder_id = var.folder_id billing_account = var.billing_account_id org_id = var.organization_id activate_apis = [] } resource "google_project_service" "enabled_services" { for_each = toset(local.project_services) project = local.project.project_id service = each.value disable_dependent_services = true disable_on_destroy = true depends_on = [ module.project_radlab_genomics ] } data "google_compute_network" "default" { count = var.create_network ? 0 : 1 project = local.project.project_id name = var.network } data "google_compute_subnetwork" "default" { count = var.create_network ? 0 : 1 project = local.project.project_id name = var.subnet region = local.region } module "vpc_ngs" { count = var.create_network ? 1 : 0 source = "terraform-google-modules/network/google" version = "~> 5.0" project_id = local.project.project_id network_name = var.network routing_mode = "GLOBAL" description = "VPC Network created via Terraform" subnets = [ { subnet_name = var.subnet subnet_ip = var.ip_cidr_range subnet_region = local.region description = "Subnetwork inside *vpc-ngs* VPC network, created via Terraform" subnet_private_access = true } ] depends_on = [ module.project_radlab_genomics, google_project_service.enabled_services, time_sleep.wait_120_seconds ] } resource "google_service_account" "sa_p_ngs" { project = local.project.project_id account_id = format("sa-p-ngs-%s", local.random_id) display_name = "NGS in trusted environment" } resource "google_project_iam_member" "sa_p_ngs_permissions" { for_each = toset(local.ngs_sa_project_roles) project = local.project.project_id member = "serviceAccount:${google_service_account.sa_p_ngs.email}" role = each.value } resource "google_service_account_iam_member" "sa_ngs_iam" { for_each = toset(concat(formatlist("user:%s", var.trusted_users), formatlist("group:%s", var.trusted_groups))) member = each.value role = "roles/iam.serviceAccountUser" service_account_id = google_service_account.sa_p_ngs.id } # Bucket to store sequence inputs and processed outputs # resource "google_storage_bucket" "input_bucket" { project = local.project.project_id name = join("", ["ngs-input-bucket-", local.random_id]) location = local.region uniform_bucket_level_access = true force_destroy = true } resource "google_storage_bucket_iam_binding" "binding1" { bucket = google_storage_bucket.input_bucket.name role = "roles/storage.admin" members = toset(concat(formatlist("user:%s", var.trusted_users), formatlist("group:%s", var.trusted_groups))) } resource "google_storage_bucket" "output_bucket" { project = local.project.project_id name = join("", ["ngs-output-bucket-", local.random_id]) location = local.region uniform_bucket_level_access = true force_destroy = true } resource "google_storage_bucket_iam_binding" "binding2" { bucket = google_storage_bucket.output_bucket.name role = "roles/storage.admin" members = toset(concat(formatlist("user:%s", var.trusted_users), formatlist("group:%s", var.trusted_groups))) } # Bucket to store Cloud functions # resource "google_storage_bucket" "source_code_bucket" { project = local.project.project_id name = join("", ["radlab-source-code-bucket-", local.random_id]) location = local.region uniform_bucket_level_access = true } data "archive_file" "source_zip" { type = "zip" output_path = "${path.module}/function-source.zip" source_dir = "${path.module}/scripts/build/cloud_functions/function-source/" } resource "google_storage_bucket_object" "archive" { name = "function-source.zip" bucket = google_storage_bucket.source_code_bucket.name source = data.archive_file.source_zip.output_path } # Create cloud functions from source code (Zip) stored in Bucket # resource "google_cloudfunctions_function" "function" { name = "ngs-qc-fastqc-fn" description = "Cloud function that uses dsub to execute pipeline jobs using lifesciences api in GCP." project = local.project.project_id runtime = "python38" region = local.region ingress_settings = "ALLOW_INTERNAL_AND_GCLB" available_memory_mb = 256 source_archive_bucket = google_storage_bucket.source_code_bucket.name source_archive_object = google_storage_bucket_object.archive.name timeout = 60 entry_point = "ngs_qc_trigger" service_account_email = google_service_account.sa_p_ngs.email labels = { my-label = "my-label-value" } event_trigger { event_type = "google.storage.object.finalize" resource = google_storage_bucket.input_bucket.name } environment_variables = { GCP_PROJECT = local.project.project_id GCS_OUTPUT_BUCKET = join("", ["gs://", google_storage_bucket.output_bucket.name]) GCS_LOG_LOCATION = join("", ["gs://", google_storage_bucket.output_bucket.name, "/logs"]) CONTAINER_IMAGE = join("", ["gcr.io/", local.project.project_id, "/fastqc:latest"]) REGION = local.region NETWORK = local.network.self_link SUBNETWORK = local.subnet.self_link ZONES = var.zone DISK_SIZE = var.boot_disk_size_gb SERVICE_ACCOUNT = google_service_account.sa_p_ngs.email } } # Locally build container for bioinformatics tool and push to container registry # resource "null_resource" "build_and_push_image" { triggers = { cloudbuild_yaml_sha = sha1(file("${path.module}/scripts/build/container/fastqc-0.11.9a/cloudbuild.yaml")) dockerfile_sha = sha1(file("${path.module}/scripts/build/container/fastqc-0.11.9a/Dockerfile")) build_script_sha = sha1(file("${path.module}/scripts/build/container/fastqc-0.11.9a/build-container.sh")) } provisioner "local-exec" { working_dir = path.module command = "bash ${path.module}/scripts/build/container/fastqc-0.11.9a/build-container.sh ${local.project.project_id} ${var.resource_creator_identity}" } }