locals { bobbin_name = "bobbin-${var.env.env_suffix}" svfe_name = "svfe-${var.env.env_suffix}" registry = "${var.env.region}-docker.pkg.dev/${var.env.project}/${var.env.registry_name}" service_accounts = { for svc, s in local.services : svc => s.sa } services = { bobbin = { name = local.bobbin_name image = "${local.registry}/${local.bobbin_name}${var.env.services.bobbin.image}" sa = google_service_account.bobbin.email invokers = ["serviceAccount:${google_service_account.svfe.email}"] probe = "/_ready" cpu = "2" memory = "2Gi" min = 1 max = 1 timeout = 3600 cpu_idle = false vpc = true env = tomap(merge({ BOBBIN_BIND = "0.0.0.0:8080" BOBBIN_LOG = "info" BOBBIN_LOG_FORMAT = "json" }, var.env.services.bobbin.env)) secrets = var.env.services.bobbin.secrets public = var.env.services.bobbin.public } svfe = { name = local.svfe_name image = "${local.registry}/${local.svfe_name}${var.env.services.svfe.image}" sa = google_service_account.svfe.email invokers = [] probe = "/oauth-client-metadata.json" cpu = "1" memory = "1Gi" min = 0 max = 4 timeout = 300 cpu_idle = true vpc = false env = tomap(var.env.services.svfe.env) secrets = var.env.services.svfe.secrets public = var.env.services.svfe.public } } robot_invoker = "serviceAccount:service-${data.google_project.this.number}@serverless-robot-prod.iam.gserviceaccount.com" apps = merge([ for svc, s in local.services : { for cell, c in var.env.regions : "${svc}-${cell}" => { region = c.region service = merge(s, { ingress = var.env.lb ? "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER" : "INGRESS_TRAFFIC_ALL" invokers = var.env.lb ? concat(s.invokers, [local.robot_invoker]) : s.invokers vpc = s.vpc ? { network = google_compute_network.this.name subnetwork = google_compute_subnetwork.this[cell].name } : null }) } } ]...) } data "google_project" "this" { project_id = var.env.project } resource "google_compute_network" "this" { project = var.env.project name = var.env.network_name auto_create_subnetworks = false } resource "google_compute_subnetwork" "this" { for_each = var.env.regions project = var.env.project name = each.value.subnet region = each.value.region network = google_compute_network.this.id ip_cidr_range = each.value.cidr stack_type = each.value.ipv6_access_type == null ? null : "IPV4_IPV6" ipv6_access_type = each.value.ipv6_access_type } resource "google_artifact_registry_repository" "this" { project = var.env.project location = var.env.region repository_id = var.env.registry_name format = "DOCKER" description = var.env.registry_description cleanup_policies { id = "keep-recent" action = "KEEP" most_recent_versions { keep_count = var.env.registry_retention.keep } } cleanup_policies { id = "delete-old-untagged" action = "DELETE" condition { tag_state = "UNTAGGED" older_than = "${var.env.registry_retention.days * 86400}s" } } # builds are tagged - and those tags never move, so without this they'd stay forever cleanup_policies { id = "delete-old-builds" action = "DELETE" condition { tag_state = "TAGGED" tag_prefixes = ["dev-", "prod-"] older_than = "${var.env.registry_retention.days * 86400}s" } } } resource "google_service_account" "bobbin" { project = var.env.project account_id = local.bobbin_name display_name = "${local.bobbin_name} cloud run runtime" } resource "google_service_account" "svfe" { project = var.env.project account_id = local.svfe_name display_name = "${local.svfe_name} cloud run runtime" } resource "google_artifact_registry_repository_iam_member" "reader" { for_each = local.service_accounts project = var.env.project location = google_artifact_registry_repository.this.location repository = google_artifact_registry_repository.this.repository_id role = "roles/artifactregistry.reader" member = "serviceAccount:${each.value}" } module "lb" { count = var.env.lb ? 1 : 0 source = "../lb" project = var.env.project name = "tangled-lb" regions = { for cell, r in var.env.regions : cell => r.region } # the app name is cell-independent, so one cell carries it into the load balancer's service map services = { for k, s in local.services : k => module.app["${k}-${keys(var.env.regions)[0]}"].name } hostnames = var.env.hostnames } module "app" { for_each = local.apps source = "../cloud-run-app" project = var.env.project region = each.value.region service = each.value.service }