main.tf (313 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 { address = var.create_address ? join("", google_compute_global_address.default[*].address) : var.address url_map = var.create_url_map ? join("", google_compute_region_url_map.default[*].self_link) : var.url_map_resource_uri create_http_forward = var.http_forward || var.https_redirect is_internal = var.load_balancing_scheme == "INTERNAL_SELF_MANAGED" # Create a map with hosts as keys and empty lists as initial values hosts = toset([for service in var.url_map_input : service.host]) backend_services_by_host = { for host in local.hosts : host => { for s in var.url_map_input : s.path => s.backend_service if s.host == host } } # Find a backend service to be used for url_map in absence of host "*" and path "/*" first_host = keys(local.backend_services_by_host)[0] first_path = keys(local.backend_services_by_host[local.first_host])[0] first_backend_service = local.backend_services_by_host[local.first_host][local.first_path] } resource "google_compute_region_backend_service" "default" { provider = google-beta project = var.project_id region = var.region name = "${var.name}-backend-service" load_balancing_scheme = var.load_balancing_scheme port_name = var.port_name protocol = var.protocol description = var.description connection_draining_timeout_sec = var.connection_draining_timeout_sec enable_cdn = var.enable_cdn session_affinity = var.session_affinity affinity_cookie_ttl_sec = var.affinity_cookie_ttl_sec locality_lb_policy = var.locality_lb_policy security_policy = var.security_policy timeout_sec = var.timeout_sec health_checks = var.health_check != null ? google_compute_region_health_check.default[*].self_link : null dynamic "backend" { for_each = toset(var.groups) content { description = lookup(backend.value, "description", null) group = backend.value["group"] balancing_mode = backend.value["balancing_mode"] capacity_scaler = backend.value["capacity_scaler"] max_connections = backend.value["max_connections"] max_connections_per_instance = backend.value["max_connections_per_instance"] max_connections_per_endpoint = backend.value["max_connections_per_endpoint"] max_rate = backend.value["max_rate"] max_rate_per_instance = backend.value["max_rate_per_instance"] max_rate_per_endpoint = backend.value["max_rate_per_endpoint"] max_utilization = backend.value["max_utilization"] } } dynamic "backend" { for_each = toset(var.serverless_neg_backends) content { group = google_compute_region_network_endpoint_group.serverless_negs["neg-${var.name}-${backend.value.region}"].id capacity_scaler = backend.value.capacity_scaler } } } resource "google_compute_region_health_check" "default" { provider = google-beta count = var.health_check != null ? 1 : 0 project = var.project_id name = "${var.name}-region-hc" region = var.region check_interval_sec = var.health_check.check_interval_sec timeout_sec = var.health_check.timeout_sec healthy_threshold = var.health_check.healthy_threshold unhealthy_threshold = var.health_check.unhealthy_threshold dynamic "http_health_check" { for_each = coalesce(var.health_check.protocol, var.protocol) == "HTTP" ? [ 1 ] : [] content { host = var.health_check.host request_path = var.health_check.request_path response = var.health_check.response port = var.health_check.port port_name = var.health_check.port_name proxy_header = var.health_check.proxy_header port_specification = var.health_check.port_specification } } dynamic "https_health_check" { for_each = coalesce(var.health_check.protocol, var.protocol) == "HTTPS" ? [ 1 ] : [] content { host = var.health_check.host request_path = var.health_check.request_path response = var.health_check.response port = var.health_check.port port_name = var.health_check.port_name proxy_header = var.health_check.proxy_header port_specification = var.health_check.port_specification } } dynamic "http2_health_check" { for_each = coalesce(var.health_check.protocol, var.protocol) == "HTTP2" ? [ 1 ] : [] content { host = var.health_check.host request_path = var.health_check.request_path response = var.health_check.response port = var.health_check.port port_name = var.health_check.port_name proxy_header = var.health_check.proxy_header port_specification = var.health_check.port_specification } } dynamic "tcp_health_check" { for_each = coalesce(var.health_check.protocol, var.protocol) == "TCP" ? [ 1 ] : [] content { request = var.health_check.request response = var.health_check.response port = var.health_check.port port_name = var.health_check.port_name proxy_header = var.health_check.proxy_header port_specification = var.health_check.port_specification } } } resource "google_compute_firewall" "default_hc" { count = var.health_check != null ? length(var.firewall_networks) : 0 project = length(var.firewall_networks) == 1 && var.firewall_projects[0] == "default" ? var.project_id : var.firewall_projects[count.index] name = "${var.name}-hc-${count.index}" network = var.firewall_networks[count.index] source_ranges = [ "130.211.0.0/22", "35.191.0.0/16" ] target_tags = length(var.target_tags) > 0 ? var.target_tags : null target_service_accounts = length(var.target_service_accounts) > 0 ? var.target_service_accounts : null allow { protocol = "tcp" ports = [var.health_check.port] } } resource "google_compute_region_network_endpoint_group" "serverless_negs" { for_each = { for serverless_neg_backend in var.serverless_neg_backends : "neg-${var.name}-${serverless_neg_backend.region}" => serverless_neg_backend } provider = google-beta project = var.project_id name = each.key network_endpoint_type = "SERVERLESS" region = each.value.region dynamic "cloud_run" { for_each = each.value.type == "cloud-run" ? [1] : [] content { service = each.value.service_name } } dynamic "cloud_function" { for_each = each.value.type == "cloud-function" ? [1] : [] content { function = each.value.service_name } } dynamic "app_engine" { for_each = each.value.type == "app-engine" ? [1] : [] content { service = each.value.service_name version = each.value.service_version } } lifecycle { create_before_destroy = true } } ### IPv4 ### resource "google_compute_forwarding_rule" "default" { provider = google-beta project = var.project_id region = var.region name = "${var.name}-forwarding-rule-http" target = google_compute_region_target_http_proxy.default[0].self_link port_range = var.http_port ip_address = local.address load_balancing_scheme = var.load_balancing_scheme labels = var.labels network = var.network } resource "google_compute_forwarding_rule" "https" { name = "${var.name}-forwarding-rule-https" project = var.project_id count = var.ssl ? 1 : 0 target = google_compute_region_target_https_proxy.default[0].self_link port_range = var.https_port load_balancing_scheme = var.load_balancing_scheme ip_address = local.address labels = var.labels network = var.network } resource "google_compute_global_address" "default" { provider = google-beta count = local.is_internal ? 0 : var.create_address ? 1 : 0 project = var.project_id name = "${var.name}-address" ip_version = "IPV4" labels = var.labels } resource "google_compute_address" "default" { provider = google-beta count = local.is_internal ? 0 : var.create_address ? 1 : 0 project = var.project_id region = var.region name = "${var.name}-address" ip_version = "IPV4" labels = var.labels } ### IPv4 ### resource "google_compute_region_url_map" "default" { count = var.create_url_map && length(local.backend_services_by_host) > 0 ? 1 : 0 provider = google-beta project = var.project_id region = var.region name = "${var.name}-url-map" default_service = lookup(lookup(local.backend_services_by_host, "*", {}), "/*", local.first_backend_service) dynamic "host_rule" { for_each = local.backend_services_by_host content { hosts = [host_rule.key] path_matcher = host_rule.key == "*" ? "default" : replace(host_rule.key, ".", "") } } dynamic "path_matcher" { for_each = local.backend_services_by_host content { name = path_matcher.key == "*" ? "default" : replace(path_matcher.key, ".", "") default_service = path_matcher.value[contains(keys(path_matcher.value), "/*") ? "/*" : keys(path_matcher.value)[0]] dynamic "path_rule" { for_each = { for k, v in path_matcher.value : k => v if k != "/*" } content { paths = [path_rule.key] service = path_rule.value } } } } } resource "google_compute_region_target_http_proxy" "default" { count = local.create_http_forward ? 1 : 0 name = "${var.name}-regional-http-proxy" project = var.project_id region = var.region url_map = var.https_redirect == false ? local.url_map : join("", google_compute_url_map.https_redirect[*].self_link) } # HTTPS proxy when ssl is true resource "google_compute_region_target_https_proxy" "default" { project = var.project_id count = var.ssl ? 1 : 0 name = "${var.name}-regional-https-proxy" region = var.region url_map = local.url_map ssl_certificates = compact(concat(var.ssl_certificates, google_compute_ssl_certificate.default[*].self_link, google_compute_managed_ssl_certificate.default[*].self_link, ), ) ssl_policy = var.ssl_policy server_tls_policy = var.server_tls_policy http_keep_alive_timeout_sec = var.http_keep_alive_timeout_sec } resource "google_compute_ssl_certificate" "default" { project = var.project_id count = var.ssl && var.create_ssl_certificate ? 1 : 0 name_prefix = "${var.name}-certificate-" private_key = var.private_key certificate = var.certificate lifecycle { create_before_destroy = true } } resource "random_id" "certificate" { count = var.random_certificate_suffix == true ? 1 : 0 byte_length = 4 prefix = "${var.name}-cert-" keepers = { domains = join(",", var.managed_ssl_certificate_domains) } } resource "google_compute_managed_ssl_certificate" "default" { provider = google-beta project = var.project_id count = var.ssl && length(var.managed_ssl_certificate_domains) > 0 ? 1 : 0 name = var.random_certificate_suffix == true ? random_id.certificate[0].hex : "${var.name}-cert" lifecycle { create_before_destroy = true } managed { domains = var.managed_ssl_certificate_domains } } resource "google_compute_url_map" "https_redirect" { project = var.project_id count = var.https_redirect ? 1 : 0 name = "${var.name}-https-redirect" default_url_redirect { https_redirect = true redirect_response_code = "MOVED_PERMANENTLY_DEFAULT" strip_query = false } }