locals { endpoints = merge([ for svc, name in var.services : { for cell, region in var.regions : "${svc}-${cell}" => { service = name region = region } } ]...) } resource "google_compute_region_network_endpoint_group" "this" { for_each = local.endpoints project = var.project name = "${each.key}-neg" region = each.value.region network_endpoint_type = "SERVERLESS" cloud_run { service = each.value.service } } resource "google_compute_backend_service" "this" { for_each = var.services project = var.project name = each.value load_balancing_scheme = "EXTERNAL_MANAGED" dynamic "backend" { for_each = var.regions content { group = google_compute_region_network_endpoint_group.this["${each.key}-${backend.key}"].id } } } resource "google_compute_url_map" "this" { for_each = var.services project = var.project name = "${var.name}-${each.key}" default_service = google_compute_backend_service.this[each.key].id } # a service with a hostname is served over https with a google-managed cert. dns # authorization lets the cert issue before the name points here, so a cutover has no gap locals { https = { for svc, host in var.hostnames : svc => host if contains(keys(var.services), svc) } } resource "google_certificate_manager_dns_authorization" "this" { for_each = local.https project = var.project name = "${var.name}-${each.key}" domain = each.value } resource "google_certificate_manager_certificate" "this" { for_each = local.https project = var.project name = "${var.name}-${each.key}" managed { domains = [each.value] dns_authorizations = [google_certificate_manager_dns_authorization.this[each.key].id] } } resource "google_certificate_manager_certificate_map" "this" { for_each = local.https project = var.project name = "${var.name}-${each.key}" } resource "google_certificate_manager_certificate_map_entry" "this" { for_each = local.https project = var.project name = "${var.name}-${each.key}" map = google_certificate_manager_certificate_map.this[each.key].name hostname = each.value certificates = [google_certificate_manager_certificate.this[each.key].id] } resource "google_compute_url_map" "to_https" { for_each = local.https project = var.project name = "${var.name}-${each.key}-to-https" default_url_redirect { https_redirect = true redirect_response_code = "MOVED_PERMANENTLY_DEFAULT" strip_query = false } } resource "google_compute_target_http_proxy" "this" { for_each = var.services project = var.project name = "${var.name}-${each.key}" url_map = contains(keys(local.https), each.key) ? google_compute_url_map.to_https[each.key].id : google_compute_url_map.this[each.key].id } resource "google_compute_target_https_proxy" "this" { for_each = local.https project = var.project name = "${var.name}-${each.key}" url_map = google_compute_url_map.this[each.key].id certificate_map = "//certificatemanager.googleapis.com/${google_certificate_manager_certificate_map.this[each.key].id}" } resource "google_compute_global_address" "this" { for_each = var.services project = var.project name = "${var.name}-${each.key}" } resource "google_compute_global_forwarding_rule" "this" { for_each = var.services project = var.project name = "${var.name}-${each.key}" ip_address = google_compute_global_address.this[each.key].id port_range = "80" target = google_compute_target_http_proxy.this[each.key].id load_balancing_scheme = "EXTERNAL_MANAGED" } resource "google_compute_global_forwarding_rule" "https" { for_each = local.https project = var.project name = "${var.name}-${each.key}-https" ip_address = google_compute_global_address.this[each.key].id port_range = "443" target = google_compute_target_https_proxy.this[each.key].id load_balancing_scheme = "EXTERNAL_MANAGED" } output "ips" { value = { for k, a in google_compute_global_address.this : k => a.address } } output "dns_records" { description = "what the dns zone needs: the address, and the record that lets the cert issue" value = { for svc, host in local.https : svc => { a = { name = host, value = google_compute_global_address.this[svc].address } challenge = one(google_certificate_manager_dns_authorization.this[svc].dns_resource_record) } } }