net-glb: Added support for regional external HTTP(s) load balancing. (#775)

This commit is contained in:
Taneli Leppä 2022-08-27 22:58:11 +02:00 committed by GitHub
parent 79c33272dd
commit c798625868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1367 additions and 154 deletions

View File

@ -481,6 +481,40 @@ resource "tls_self_signed_cert" "self_signed_cert" {
# tftest modules=1 resources=6
```
## Regional Load Balancing
You can also use regional load balancing by specifying a `region` parameter:
```hcl
module "glb" {
source = "./modules/net-glb"
name = "glb-test"
project_id = var.project_id
region = var.region
backend_services_config = {
my-group-backend = {
bucket_config = null
enable_cdn = false
cdn_config = null
group_config = {
backends = [
{
group = "my_test_group"
options = null
}
],
health_checks = []
log_config = null
options = null
}
}
}
}
# tftest modules=1 resources=5
```
## Components And Files Mapping
An External Global Load Balancer is made of multiple components, that change depending on the configurations. Sometimes, it may be tricky to understand what they are, and how they relate to each other. Following, we provide a very brief overview to become more familiar with them.
@ -500,10 +534,13 @@ Target proxies leverage [url-maps](url-map.tf): set of L7 rules, which create a
|---|---|---|
| [backend-services.tf](./backend-services.tf) | Bucket and group backend services. | <code>google_compute_backend_bucket</code> · <code>google_compute_backend_service</code> |
| [global-forwarding-rule.tf](./global-forwarding-rule.tf) | Global address and forwarding rule. | <code>google_compute_global_address</code> · <code>google_compute_global_forwarding_rule</code> |
| [health-checks.tf](./health-checks.tf) | Health checks. | <code>google_compute_health_check</code> |
| [health-checks.tf](./health-checks.tf) | Health checks. | <code>google_compute_health_check</code> · <code>google_compute_region_health_check</code> |
| [outputs.tf](./outputs.tf) | Module outputs. | |
| [regional-backend-services.tf](./regional-backend-services.tf) | Bucket and group backend services for regional load balancers. | <code>google_compute_region_backend_service</code> |
| [regional-forwarding-rule.tf](./regional-forwarding-rule.tf) | Global address and forwarding rule. | <code>google_compute_address</code> · <code>google_compute_forwarding_rule</code> |
| [regional-url-map.tf](./regional-url-map.tf) | regional URL maps. | <code>google_compute_region_url_map</code> |
| [ssl-certificates.tf](./ssl-certificates.tf) | SSL certificates. | <code>google_compute_managed_ssl_certificate</code> · <code>google_compute_ssl_certificate</code> |
| [target-proxy.tf](./target-proxy.tf) | HTTP and HTTPS target proxies. | <code>google_compute_target_http_proxy</code> · <code>google_compute_target_https_proxy</code> |
| [target-proxy.tf](./target-proxy.tf) | HTTP and HTTPS target proxies. | <code>google_compute_region_target_http_proxy</code> · <code>google_compute_region_target_https_proxy</code> · <code>google_compute_target_http_proxy</code> · <code>google_compute_target_https_proxy</code> |
| [url-map.tf](./url-map.tf) | URL maps. | <code>google_compute_url_map</code> |
| [variables.tf](./variables.tf) | Module variables. | |
| [versions.tf](./versions.tf) | Version pins. | |
@ -514,22 +551,25 @@ Target proxies leverage [url-maps](url-map.tf): set of L7 rules, which create a
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L17) | Load balancer name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L22) | Project id. | <code>string</code> | ✓ | |
| [backend_services_config](variables.tf#L56) | The backends services configuration. | <code title="map&#40;object&#40;&#123;&#10; enable_cdn &#61; bool&#10;&#10;&#10; cdn_config &#61; object&#40;&#123;&#10; cache_mode &#61; string&#10; client_ttl &#61; number&#10; default_ttl &#61; number&#10; max_ttl &#61; number&#10; negative_caching &#61; bool&#10; negative_caching_policy &#61; map&#40;number&#41;&#10; serve_while_stale &#61; bool&#10; signed_url_cache_max_age_sec &#61; string&#10; &#125;&#41;&#10;&#10;&#10; bucket_config &#61; object&#40;&#123;&#10; bucket_name &#61; string&#10; options &#61; object&#40;&#123;&#10; custom_response_headers &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#10;&#10; group_config &#61; object&#40;&#123;&#10; backends &#61; list&#40;object&#40;&#123;&#10; group &#61; string &#35; IG or NEG FQDN address&#10; options &#61; object&#40;&#123;&#10; balancing_mode &#61; string &#35; Can be UTILIZATION, RATE, CONNECTION&#10; capacity_scaler &#61; number &#35; Valid range is &#91;0.0,1.0&#93;&#10; max_connections &#61; number&#10; max_connections_per_instance &#61; number&#10; max_connections_per_endpoint &#61; number&#10; max_rate &#61; number&#10; max_rate_per_instance &#61; number&#10; max_rate_per_endpoint &#61; number&#10; max_utilization &#61; number&#10; &#125;&#41;&#10; &#125;&#41;&#41;&#10; health_checks &#61; list&#40;string&#41;&#10;&#10;&#10; log_config &#61; object&#40;&#123;&#10; enable &#61; bool&#10; sample_rate &#61; number &#35; must be in &#91;0, 1&#93;&#10; &#125;&#41;&#10;&#10;&#10; options &#61; object&#40;&#123;&#10; affinity_cookie_ttl_sec &#61; number&#10; custom_request_headers &#61; list&#40;string&#41;&#10; custom_response_headers &#61; list&#40;string&#41;&#10; connection_draining_timeout_sec &#61; number&#10; load_balancing_scheme &#61; string &#35; only EXTERNAL &#40;default&#41; makes sense here&#10; locality_lb_policy &#61; string&#10; port_name &#61; string&#10; protocol &#61; string&#10; security_policy &#61; string&#10; session_affinity &#61; string&#10; timeout_sec &#61; number&#10;&#10;&#10; circuits_breakers &#61; object&#40;&#123;&#10; max_requests_per_connection &#61; number &#35; Set to 1 to disable keep-alive&#10; max_connections &#61; number &#35; Defaults to 1024&#10; max_pending_requests &#61; number &#35; Defaults to 1024&#10; max_requests &#61; number &#35; Defaults to 1024&#10; max_retries &#61; number &#35; Defaults to 3&#10; &#125;&#41;&#10;&#10;&#10; consistent_hash &#61; object&#40;&#123;&#10; http_header_name &#61; string&#10; minimum_ring_size &#61; string&#10; http_cookie &#61; object&#40;&#123;&#10; name &#61; string&#10; path &#61; string&#10; ttl &#61; object&#40;&#123;&#10; seconds &#61; number&#10; nanos &#61; number&#10; &#125;&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#10;&#10; iap &#61; object&#40;&#123;&#10; oauth2_client_id &#61; string&#10; oauth2_client_secret &#61; string&#10; oauth2_client_secret_sha256 &#61; string&#10; &#125;&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [global_forwarding_rule_config](variables.tf#L202) | Global forwarding rule configurations. | <code title="object&#40;&#123;&#10; ip_protocol &#61; string&#10; ip_version &#61; string&#10; load_balancing_scheme &#61; string&#10; port_range &#61; string&#10;&#10;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; load_balancing_scheme &#61; &#34;EXTERNAL&#34;&#10; ip_protocol &#61; &#34;TCP&#34;&#10; ip_version &#61; &#34;IPV4&#34;&#10; port_range &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [health_checks_config](variables.tf#L45) | Custom health checks configuration. | <code title="map&#40;object&#40;&#123;&#10; type &#61; string &#35; http https tcp ssl http2&#10; check &#61; map&#40;any&#41; &#35; actual health check block attributes&#10; options &#61; map&#40;number&#41; &#35; interval, thresholds, timeout&#10; logging &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_checks_config_defaults](variables.tf#L27) | Auto-created health check default configuration. | <code title="object&#40;&#123;&#10; type &#61; string &#35; http https tcp ssl http2&#10; check &#61; map&#40;any&#41; &#35; actual health check block attributes&#10; options &#61; map&#40;number&#41; &#35; interval, thresholds, timeout&#10; logging &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; type &#61; &#34;http&#34;&#10; logging &#61; false&#10; options &#61; &#123;&#125;&#10; check &#61; &#123;&#10; port_specification &#61; &#34;USE_SERVING_PORT&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [https](variables.tf#L220) | Whether to enable HTTPS. | <code>bool</code> | | <code>false</code> |
| [reserve_ip_address](variables.tf#L226) | Whether to reserve a static global IP address. | <code>bool</code> | | <code>false</code> |
| [ssl_certificates_config](variables.tf#L165) | The SSL certificate configuration. | <code title="map&#40;object&#40;&#123;&#10; domains &#61; list&#40;string&#41;&#10; unmanaged_config &#61; object&#40;&#123;&#10; tls_private_key &#61; string&#10; tls_self_signed_cert &#61; string&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [ssl_certificates_config_defaults](variables.tf#L178) | The SSL certificate default configuration. | <code title="object&#40;&#123;&#10; domains &#61; list&#40;string&#41;&#10; unmanaged_config &#61; object&#40;&#123;&#10; tls_private_key &#61; string&#10; tls_self_signed_cert &#61; string&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; domains &#61; &#91;&#34;example.com&#34;&#93;,&#10; unmanaged_config &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [target_proxy_https_config](variables.tf#L194) | The HTTPS target proxy configuration. | <code title="object&#40;&#123;&#10; ssl_certificates &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [url_map_config](variables.tf#L151) | The url-map configuration. | <code title="object&#40;&#123;&#10; default_service &#61; string&#10; default_route_action &#61; any&#10; default_url_redirect &#61; map&#40;any&#41;&#10; header_action &#61; any&#10; host_rules &#61; list&#40;any&#41;&#10; path_matchers &#61; list&#40;any&#41;&#10; tests &#61; list&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [backend_services_config](variables.tf#L62) | The backends services configuration. | <code title="map&#40;object&#40;&#123;&#10; enable_cdn &#61; bool&#10;&#10;&#10; cdn_config &#61; object&#40;&#123;&#10; cache_mode &#61; string&#10; client_ttl &#61; number&#10; default_ttl &#61; number&#10; max_ttl &#61; number&#10; negative_caching &#61; bool&#10; negative_caching_policy &#61; map&#40;number&#41;&#10; serve_while_stale &#61; bool&#10; signed_url_cache_max_age_sec &#61; string&#10; &#125;&#41;&#10;&#10;&#10; bucket_config &#61; object&#40;&#123;&#10; bucket_name &#61; string&#10; options &#61; object&#40;&#123;&#10; custom_response_headers &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#10;&#10; group_config &#61; object&#40;&#123;&#10; backends &#61; list&#40;object&#40;&#123;&#10; group &#61; string &#35; IG or NEG FQDN address&#10; options &#61; object&#40;&#123;&#10; balancing_mode &#61; string &#35; Can be UTILIZATION, RATE, CONNECTION&#10; capacity_scaler &#61; number &#35; Valid range is &#91;0.0,1.0&#93;&#10; max_connections &#61; number&#10; max_connections_per_instance &#61; number&#10; max_connections_per_endpoint &#61; number&#10; max_rate &#61; number&#10; max_rate_per_instance &#61; number&#10; max_rate_per_endpoint &#61; number&#10; max_utilization &#61; number&#10; &#125;&#41;&#10; &#125;&#41;&#41;&#10; health_checks &#61; list&#40;string&#41;&#10;&#10;&#10; log_config &#61; object&#40;&#123;&#10; enable &#61; bool&#10; sample_rate &#61; number &#35; must be in &#91;0, 1&#93;&#10; &#125;&#41;&#10;&#10;&#10; options &#61; object&#40;&#123;&#10; affinity_cookie_ttl_sec &#61; number&#10; custom_request_headers &#61; list&#40;string&#41;&#10; custom_response_headers &#61; list&#40;string&#41;&#10; connection_draining_timeout_sec &#61; number&#10; load_balancing_scheme &#61; string &#35; only EXTERNAL &#40;default&#41; makes sense here&#10; locality_lb_policy &#61; string&#10; port_name &#61; string&#10; protocol &#61; string&#10; security_policy &#61; string&#10; session_affinity &#61; string&#10; timeout_sec &#61; number&#10;&#10;&#10; circuits_breakers &#61; object&#40;&#123;&#10; max_requests_per_connection &#61; number &#35; Set to 1 to disable keep-alive&#10; max_connections &#61; number &#35; Defaults to 1024&#10; max_pending_requests &#61; number &#35; Defaults to 1024&#10; max_requests &#61; number &#35; Defaults to 1024&#10; max_retries &#61; number &#35; Defaults to 3&#10; &#125;&#41;&#10;&#10;&#10; consistent_hash &#61; object&#40;&#123;&#10; http_header_name &#61; string&#10; minimum_ring_size &#61; string&#10; http_cookie &#61; object&#40;&#123;&#10; name &#61; string&#10; path &#61; string&#10; ttl &#61; object&#40;&#123;&#10; seconds &#61; number&#10; nanos &#61; number&#10; &#125;&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#10;&#10; iap &#61; object&#40;&#123;&#10; oauth2_client_id &#61; string&#10; oauth2_client_secret &#61; string&#10; oauth2_client_secret_sha256 &#61; string&#10; &#125;&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [forwarding_rule_config](variables.tf#L226) | Regional forwarding rule configurations. | <code title="object&#40;&#123;&#10; ip_protocol &#61; string&#10; ip_version &#61; string&#10; load_balancing_scheme &#61; string&#10; port_range &#61; string&#10; network_tier &#61; string&#10; network &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; load_balancing_scheme &#61; &#34;EXTERNAL_MANAGED&#34;&#10; ip_protocol &#61; &#34;TCP&#34;&#10; ip_version &#61; &#34;IPV4&#34;&#10; network_tier &#61; &#34;STANDARD&#34;&#10; network &#61; &#34;default&#34;&#10; port_range &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [global_forwarding_rule_config](variables.tf#L208) | Global forwarding rule configurations. | <code title="object&#40;&#123;&#10; ip_protocol &#61; string&#10; ip_version &#61; string&#10; load_balancing_scheme &#61; string&#10; port_range &#61; string&#10;&#10;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; load_balancing_scheme &#61; &#34;EXTERNAL&#34;&#10; ip_protocol &#61; &#34;TCP&#34;&#10; ip_version &#61; &#34;IPV4&#34;&#10; port_range &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [health_checks_config](variables.tf#L51) | Custom health checks configuration. | <code title="map&#40;object&#40;&#123;&#10; type &#61; string &#35; http https tcp ssl http2&#10; check &#61; map&#40;any&#41; &#35; actual health check block attributes&#10; options &#61; map&#40;number&#41; &#35; interval, thresholds, timeout&#10; logging &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_checks_config_defaults](variables.tf#L33) | Auto-created health check default configuration. | <code title="object&#40;&#123;&#10; type &#61; string &#35; http https tcp ssl http2&#10; check &#61; map&#40;any&#41; &#35; actual health check block attributes&#10; options &#61; map&#40;number&#41; &#35; interval, thresholds, timeout&#10; logging &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; type &#61; &#34;http&#34;&#10; logging &#61; false&#10; options &#61; &#123;&#125;&#10; check &#61; &#123;&#10; port_specification &#61; &#34;USE_SERVING_PORT&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [https](variables.tf#L247) | Whether to enable HTTPS. | <code>bool</code> | | <code>false</code> |
| [region](variables.tf#L27) | Create a regional load balancer in this region. | <code>string</code> | | <code>null</code> |
| [reserve_ip_address](variables.tf#L253) | Whether to reserve a static global IP address. | <code>bool</code> | | <code>false</code> |
| [ssl_certificates_config](variables.tf#L171) | The SSL certificate configuration. | <code title="map&#40;object&#40;&#123;&#10; domains &#61; list&#40;string&#41;&#10; unmanaged_config &#61; object&#40;&#123;&#10; tls_private_key &#61; string&#10; tls_self_signed_cert &#61; string&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [ssl_certificates_config_defaults](variables.tf#L184) | The SSL certificate default configuration. | <code title="object&#40;&#123;&#10; domains &#61; list&#40;string&#41;&#10; unmanaged_config &#61; object&#40;&#123;&#10; tls_private_key &#61; string&#10; tls_self_signed_cert &#61; string&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; domains &#61; &#91;&#34;example.com&#34;&#93;,&#10; unmanaged_config &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [target_proxy_https_config](variables.tf#L200) | The HTTPS target proxy configuration. | <code title="object&#40;&#123;&#10; ssl_certificates &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [url_map_config](variables.tf#L157) | The url-map configuration. | <code title="object&#40;&#123;&#10; default_service &#61; string&#10; default_route_action &#61; any&#10; default_url_redirect &#61; map&#40;any&#41;&#10; header_action &#61; any&#10; host_rules &#61; list&#40;any&#41;&#10; path_matchers &#61; list&#40;any&#41;&#10; tests &#61; list&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [backend_services](outputs.tf#L22) | Backend service resources. | |
| [forwarding_rule](outputs.tf#L67) | The regional forwarding rule. | |
| [global_forwarding_rule](outputs.tf#L62) | The global forwarding rule. | |
| [health_checks](outputs.tf#L17) | Health-check resources. | |
| [ip_address](outputs.tf#L44) | The reserved global IP address. | |

View File

@ -60,7 +60,7 @@ resource "google_compute_backend_bucket" "bucket" {
}
resource "google_compute_backend_service" "group" {
for_each = local.backend_services_group
for_each = var.region == null ? local.backend_services_group : {}
name = "${var.name}-${each.key}"
project = var.project_id
description = "Terraform managed."
@ -208,3 +208,4 @@ resource "google_compute_backend_service" "group" {
}
}
}

View File

@ -17,26 +17,26 @@
# tfdoc:file:description Global address and forwarding rule.
locals {
ip_address = (
var.reserve_ip_address
ip_address = var.region == null ? (
var.region == null && var.reserve_ip_address
? google_compute_global_address.static_ip.0.id
: null
)
) : null
port_range = coalesce(
var.global_forwarding_rule_config.port_range,
var.https ? "443" : "80"
)
target = (
target = var.region == null ? (
var.https
? google_compute_target_https_proxy.https.0.id
: google_compute_target_http_proxy.http.0.id
)
) : null
}
resource "google_compute_global_address" "static_ip" {
count = var.reserve_ip_address ? 1 : 0
count = var.region == null && var.reserve_ip_address ? 1 : 0
provider = google-beta
name = var.name
project = var.project_id
@ -44,6 +44,7 @@ resource "google_compute_global_address" "static_ip" {
}
resource "google_compute_global_forwarding_rule" "forwarding_rule" {
count = var.region == null ? 1 : 0
provider = google-beta
name = var.name
project = var.project_id

View File

@ -48,7 +48,7 @@ locals {
}
resource "google_compute_health_check" "health_check" {
for_each = local.health_checks_config
for_each = var.region == null ? local.health_checks_config : {}
provider = google-beta
name = "${var.name}-${each.key}"
project = var.project_id
@ -148,3 +148,106 @@ resource "google_compute_health_check" "health_check" {
}
}
}
resource "google_compute_region_health_check" "health_check" {
for_each = var.region != null ? local.health_checks_config : {}
provider = google-beta
name = "${var.name}-${each.key}"
project = var.project_id
region = var.region
description = "Terraform managed."
check_interval_sec = try(each.value.options.check_interval_sec, null)
healthy_threshold = try(each.value.options.healthy_threshold, null)
timeout_sec = try(each.value.options.timeout_sec, null)
unhealthy_threshold = try(each.value.options.unhealthy_threshold, null)
dynamic "http_health_check" {
for_each = (
try(each.value.type, null) == "http" || try(each.value.type, null) == null
? { 1 = 1 }
: {}
)
content {
host = try(each.value.check.host, null)
port = try(each.value.check.port, null)
port_name = try(each.value.check.port_name, null)
port_specification = try(each.value.check.port_specification, null)
proxy_header = try(each.value.check.proxy_header, null)
request_path = try(each.value.check.request_path, null)
response = try(each.value.check.response, null)
}
}
dynamic "https_health_check" {
for_each = (
try(each.value.type, null) == "https" || try(each.value.type, null) == null
? { 1 = 1 }
: {}
)
content {
host = try(each.value.check.host, null)
port = try(each.value.check.port, null)
port_name = try(each.value.check.port_name, null)
port_specification = try(each.value.check.port_specification, null)
proxy_header = try(each.value.check.proxy_header, null)
request_path = try(each.value.check.request_path, null)
response = try(each.value.check.response, null)
}
}
dynamic "tcp_health_check" {
for_each = (
try(each.value.type, null) == "tcp" || try(each.value.type, null) == null
? { 1 = 1 }
: {}
)
content {
port = try(each.value.check.port, null)
port_name = try(each.value.check.port_name, null)
port_specification = try(each.value.check.port_specification, null)
proxy_header = try(each.value.check.proxy_header, null)
request = try(each.value.check.request, null)
response = try(each.value.check.response, null)
}
}
dynamic "ssl_health_check" {
for_each = (
try(each.value.type, null) == "ssl" || try(each.value.type, null) == null
? { 1 = 1 }
: {}
)
content {
port = try(each.value.check.port, null)
port_name = try(each.value.check.port_name, null)
port_specification = try(each.value.check.port_specification, null)
proxy_header = try(each.value.check.proxy_header, null)
request = try(each.value.check.request, null)
response = try(each.value.check.response, null)
}
}
dynamic "http2_health_check" {
for_each = (
try(each.value.type, null) == "http2" || try(each.value.type, null) == null
? { 1 = 1 }
: {}
)
content {
host = try(each.value.check.host, null)
port = try(each.value.check.port, null)
port_name = try(each.value.check.port_name, null)
port_specification = try(each.value.check.port_specification, null)
proxy_header = try(each.value.check.proxy_header, null)
request_path = try(each.value.check.request_path, null)
response = try(each.value.check.response, null)
}
}
dynamic "log_config" {
for_each = try(each.value.logging, false) ? { 0 = 0 } : {}
content {
enable = true
}
}
}

View File

@ -43,12 +43,12 @@ output "ssl_certificates" {
output "ip_address" {
description = "The reserved global IP address."
value = try(google_compute_global_address.static_ip[0].address, null)
value = var.region == null ? try(google_compute_global_address.static_ip.0.address, null) : try(google_compute_address.static_ip.0.address, null)
}
output "ip_address_self_link" {
description = "The URI of the reserved global IP address."
value = google_compute_global_forwarding_rule.forwarding_rule.ip_address
value = var.region == null ? google_compute_global_forwarding_rule.forwarding_rule.0.ip_address : google_compute_forwarding_rule.forwarding_rule.0.ip_address
}
output "target_proxy" {
@ -61,5 +61,10 @@ output "target_proxy" {
output "global_forwarding_rule" {
description = "The global forwarding rule."
value = google_compute_global_forwarding_rule.forwarding_rule
value = var.region == null ? google_compute_global_forwarding_rule.forwarding_rule.0 : null
}
output "forwarding_rule" {
description = "The regional forwarding rule."
value = var.region == null ? google_compute_global_forwarding_rule.forwarding_rule.0 : google_compute_forwarding_rule.forwarding_rule.0
}

View File

@ -0,0 +1,164 @@
/**
* Copyright 2022 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.
*/
# tfdoc:file:description Bucket and group backend services for regional load balancers.
resource "google_compute_region_backend_service" "group" {
for_each = var.region != null ? local.backend_services_group : {}
name = "${var.name}-${each.key}"
project = var.project_id
region = var.region
description = "Terraform managed."
affinity_cookie_ttl_sec = try(each.value.group_config.options.affinity_cookie_ttl_sec, null)
enable_cdn = try(each.value.enable_cdn, null)
connection_draining_timeout_sec = try(each.value.group_config.options.connection_draining_timeout_sec, null)
load_balancing_scheme = try(each.value.group_config.options.load_balancing_scheme, null)
locality_lb_policy = try(each.value.group_config.options.locality_lb_policy, null)
port_name = try(each.value.group_config.options.port_name, null)
protocol = try(each.value.group_config.options.protocol, null)
session_affinity = try(each.value.group_config.options.session_affinity, null)
timeout_sec = try(each.value.group_config.options.timeout_sec, null)
# If no health checks are defined, use the default one.
# Otherwise, look in the health_checks_config map.
# Otherwise, use the health_check id as is (already existing).
health_checks = (
try(length(each.value.group_config.health_checks), 0) == 0
? try(
[google_compute_region_health_check.health_check["default"].id],
null
)
: [
for hc in each.value.group_config.health_checks :
try(google_compute_region_health_check.health_check[hc].id, hc)
]
)
dynamic "backend" {
for_each = try(each.value.group_config.backends, [])
content {
balancing_mode = try(backend.value.options.balancing_mode, null)
capacity_scaler = try(backend.value.options.capacity_scaler, null)
group = try(backend.value.group, null)
max_connections = try(backend.value.options.max_connections, null)
max_connections_per_instance = try(backend.value.options.max_connections_per_instance, null)
max_connections_per_endpoint = try(backend.value.options.max_connections_per_endpoint, null)
max_rate = try(backend.value.options.max_rate, null)
max_rate_per_instance = try(backend.value.options.max_rate_per_instance, null)
max_rate_per_endpoint = try(backend.value.options.max_rate_per_endpoint, null)
max_utilization = try(backend.value.options.max_utilization, null)
}
}
dynamic "circuit_breakers" {
for_each = (
try(each.value.group_config.options.circuit_breakers, null) == null
? []
: [each.value.group_config.options.circuit_breakers]
)
iterator = cb
content {
max_requests_per_connection = try(cb.value.max_requests_per_connection, null)
max_connections = try(cb.value.max_connections, null)
max_pending_requests = try(cb.value.max_pending_requests, null)
max_requests = try(cb.value.max_requests, null)
max_retries = try(cb.value.max_retries, null)
}
}
dynamic "consistent_hash" {
for_each = (
try(each.value.group_config.options.consistent_hash, null) == null
? []
: [each.value.group_config.options.consistent_hash]
)
content {
http_header_name = try(consistent_hash.value.http_header_name, null)
minimum_ring_size = try(consistent_hash.value.minimum_ring_size, null)
dynamic "http_cookie" {
for_each = try(consistent_hash.value.http_cookie, null) == null ? [] : [consistent_hash.value.http_cookie]
content {
name = try(http_cookie.value.name, null)
path = try(http_cookie.value.path, null)
dynamic "ttl" {
for_each = try(consistent_hash.value.ttl, null) == null ? [] : [consistent_hash.value.ttl]
content {
seconds = try(ttl.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
nanos = try(ttl.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
}
}
}
}
}
}
dynamic "cdn_policy" {
for_each = (
try(each.value.cdn_policy, null) == null
? []
: [each.value.cdn_policy]
)
iterator = cdn_policy
content {
signed_url_cache_max_age_sec = try(cdn_policy.value.signed_url_cache_max_age_sec, null)
default_ttl = try(cdn_policy.value.default_ttl, null)
max_ttl = try(cdn_policy.value.max_ttl, null)
client_ttl = try(cdn_policy.value.client_ttl, null)
negative_caching = try(cdn_policy.value.negative_caching, null)
cache_mode = try(cdn_policy.value.cache_mode, null)
serve_while_stale = try(cdn_policy.value.serve_while_stale, null)
dynamic "negative_caching_policy" {
for_each = (
try(cdn_policy.value.negative_caching_policy, null) == null
? []
: [cdn_policy.value.negative_caching_policy]
)
iterator = ncp
content {
code = try(ncp.value.code, null)
}
}
}
}
dynamic "iap" {
for_each = (
try(each.value.group_config.options.iap, null) == null
? []
: [each.value.group_config.options.iap]
)
content {
oauth2_client_id = try(iap.value.oauth2_client_id, null)
oauth2_client_secret = try(iap.value.oauth2_client_secret, null) # sensitive
oauth2_client_secret_sha256 = try(iap.value.oauth2_client_secret_sha256, null) # sensitive
}
}
dynamic "log_config" {
for_each = (
try(each.value.group_config.log_config, null) == null
? []
: [each.value.group_config.log_config]
)
content {
enable = try(log_config.value.enable, null)
sample_rate = try(log_config.value.sample_rate, null)
}
}
}

View File

@ -0,0 +1,62 @@
/**
* Copyright 2022 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.
*/
# tfdoc:file:description Global address and forwarding rule.
locals {
regional_ip_address = var.region != null ? (
var.reserve_ip_address
? google_compute_address.static_ip.0.id
: null
) : null
regional_port_range = coalesce(
var.forwarding_rule_config.port_range,
var.https ? "443" : "80"
)
regional_target = var.region != null ? (
var.https
? google_compute_region_target_https_proxy.https.0.id
: google_compute_region_target_http_proxy.http.0.id
) : null
}
resource "google_compute_address" "static_ip" {
count = var.region != null && var.reserve_ip_address ? 1 : 0
provider = google-beta
name = var.name
project = var.project_id
region = var.region
description = "Terraform managed."
address_type = "EXTERNAL"
}
resource "google_compute_forwarding_rule" "forwarding_rule" {
count = var.region != null ? 1 : 0
provider = google-beta
name = var.name
project = var.project_id
region = var.region
description = "Terraform managed."
ip_protocol = var.forwarding_rule_config.ip_protocol
load_balancing_scheme = var.forwarding_rule_config.load_balancing_scheme
port_range = local.regional_port_range
target = local.regional_target
ip_address = local.regional_ip_address
network_tier = var.forwarding_rule_config.network_tier
network = var.forwarding_rule_config.network
}

View File

@ -0,0 +1,717 @@
/**
* Copyright 2022 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.
*/
# tfdoc:file:description regional URL maps.
locals {
# Look for a backend services in the config whose id is
# the default_service given in the url-map.
# If not found, use the default_service id as given
# (assuming it's already existing).
# If the variable is null, will be set to null.
_regional_default_service = try(
google_compute_backend_bucket.bucket[var.url_map_config.default_service].id,
google_compute_region_backend_service.group[var.url_map_config.default_service].id,
var.url_map_config.default_service,
null
)
# If no backend services are specified,
# the first backend service defined is associated
regional_default_service = (
try(local._regional_default_service, null) == null
&& try(var.url_map_config.default_route_action.weighted_backend_services, null) == null
&& try(var.url_map_config.default_url_redirect, null) == null
? try(
google_compute_backend_bucket.bucket[keys(google_compute_backend_bucket.bucket)[0]].id,
google_compute_region_backend_service.group[keys(google_compute_region_backend_service.group)[0]].id,
null
)
: null
)
}
resource "google_compute_region_url_map" "url_map" {
count = var.region != null ? 1 : 0
name = var.name
description = "Terraform managed."
project = var.project_id
region = var.region
default_service = local.regional_default_service
dynamic "host_rule" {
for_each = (
try(var.url_map_config.host_rules, null) == null
? []
: var.url_map_config.host_rules
)
content {
description = try(host_rule.value.description, null)
hosts = try(host_rule.value.hosts, null)
path_matcher = try(host_rule.value.path_matcher, null)
}
}
dynamic "path_matcher" {
for_each = (
try(var.url_map_config.path_matchers, null) == null
? []
: var.url_map_config.path_matchers
)
content {
name = try(path_matcher.value.name, null)
description = try(path_matcher.value.description, null)
default_service = try(
google_compute_backend_bucket.bucket[var.url_map_config.default_service].id,
google_compute_region_backend_service.group[var.url_map_config.default_service].id,
path_matcher.value.default_service,
null
)
dynamic "path_rule" {
for_each = (
try(path_matcher.value.path_rules, null) == null
? []
: path_matcher.value.path_rules
)
content {
paths = try(path_rule.value.paths, null)
service = try(
google_compute_backend_bucket.bucket[path_rule.value.service].id,
google_compute_region_backend_service.group[path_rule.value.service].id,
path_rule.value.service,
null
)
dynamic "route_action" {
for_each = (
try(path_rule.value.route_action, null) == null
? []
: [path_rule.value.route_action]
)
content {
dynamic "cors_policy" {
for_each = (
try(route_action.value.cors_policy, null) == null
? []
: [route_action.value.cors_policy]
)
content {
allow_credentials = try(cors_policy.value.allow_credentials, null)
allow_headers = try(cors_policy.value.allow_headers, null)
allow_methods = try(cors_policy.value.allow_methods, null)
allow_origin_regexes = try(cors_policy.value.allow_origin_regexes, null)
allow_origins = try(cors_policy.value.allow_origins, null)
disabled = try(cors_policy.value.disabled, null)
expose_headers = try(cors_policy.value.expose_headers, null)
max_age = try(cors_policy.value.max_age, null)
}
}
dynamic "fault_injection_policy" {
for_each = (
try(route_action.value.fault_injection_policy, null) == null
? []
: [route_action.value.fault_injection_policy]
)
iterator = policy
content {
dynamic "abort" {
for_each = (
try(policy.value.abort, null) == null
? []
: [policy.value.abort]
)
content {
http_status = try(abort.value.http_status, null) # Must be between 200 and 599 inclusive
percentage = try(abort.value.percentage, null) # Must be between 0.0 and 100.0 inclusive
}
}
dynamic "delay" {
for_each = (
try(policy.value.delay, null) == null
? []
: [policy.value.delay]
)
content {
percentage = try(delay.value.percentage, null) # Must be between 0.0 and 100.0 inclusive
dynamic "fixed_delay" {
for_each = (
try(delay.value.fixed_delay, null) == null
? []
: [delay.value.fixed_delay]
)
content {
nanos = try(fixed_delay.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
seconds = try(fixed_delay.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
}
}
}
}
}
}
dynamic "request_mirror_policy" {
for_each = (
try(route_action.value.request_mirror_policy, null) == null
? []
: [route_action.value.request_mirror_policy]
)
iterator = policy
content {
backend_service = try(
google_compute_backend_bucket.bucket[policy.value.backend_service].id,
google_compute_region_backend_service.group[policy.value.backend_service].id,
policy.value.backend_service,
null
)
}
}
dynamic "retry_policy" {
for_each = (
try(route_action.value.retry_policy, null) == null
? []
: [route_action.value.retry_policy]
)
iterator = policy
content {
num_retries = try(policy.num_retries, null) # Must be > 0
# Valid values at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#retry_conditions
retry_conditions = try(policy.retry_conditions, null)
dynamic "per_try_timeout" {
for_each = (
try(policy.value.per_try_timeout, null) == null
? []
: [policy.value.per_try_timeout]
)
iterator = timeout
content {
nanos = try(timeout.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
seconds = try(timeout.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
}
}
}
}
dynamic "timeout" {
for_each = (
try(route_action.value.timeout, null) == null
? []
: [route_action.value.timeout]
)
content {
nanos = try(timeout.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
seconds = try(timeout.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
}
}
dynamic "url_rewrite" {
for_each = (
try(route_action.value.url_rewrite, null) == null
? []
: [route_action.value.url_rewrite]
)
content {
host_rewrite = try(url_rewrite.value.host_rewrite, null) # Must be between 1 and 255 characters
path_prefix_rewrite = try(url_rewrite.value.path_prefix_rewrite, null) # Must be between 1 and 1024 characters
}
}
dynamic "weighted_backend_services" {
for_each = (
try(route_action.value.weighted_backend_services, null) == null
? []
: route_action.value.weighted_backend_services
)
iterator = weighted
content {
weight = try(weighted.value.weigth, null)
backend_service = try(
google_compute_backend_bucket.bucket[weighted.value.backend_service].id,
google_compute_backend_service.group[weighted.value.backend_service].id,
policy.value.backend_service,
null
)
dynamic "header_action" {
for_each = (
try(path_matcher.value.header_action, null) == null
? []
: [path_matcher.value.header_action]
)
content {
request_headers_to_remove = try(header_action.value.request_headers_to_remove, null)
response_headers_to_remove = try(header_action.value.response_headers_to_remove, null)
dynamic "request_headers_to_add" {
for_each = (
try(header_action.value.request_headers_to_add, null) == null
? [] :
[header_action.value.request_headers_to_add]
)
content {
header_name = try(request_headers_to_add.value.header_name, null)
header_value = try(request_headers_to_add.value.header_value, null)
replace = try(request_headers_to_add.value.replace, null)
}
}
dynamic "response_headers_to_add" {
for_each = (
try(header_action.response_headers_to_add, null) == null
? []
: [header_action.response_headers_to_add]
)
content {
header_name = try(response_headers_to_add.value.header_name, null)
header_value = try(response_headers_to_add.value.header_value, null)
replace = try(response_headers_to_add.value.replace, null)
}
}
}
}
}
}
}
}
dynamic "url_redirect" {
for_each = (
try(path_rule.value.url_redirect, null) == null
? []
: path_rule.value.url_redirect
)
content {
host_redirect = try(url_redirect.value.host_redirect, null) # Must be between 1 and 255 characters
https_redirect = try(url_redirect.value.https_redirect, null)
path_redirect = try(url_redirect.value.path_redirect, null)
prefix_redirect = try(url_redirect.value.prefix_redirect, null) # Must be between 1 and 1024 characters
# Valid valus at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#redirect_response_code
redirect_response_code = try(url_redirect.value.redirect_response_code, null)
strip_query = try(url_redirect.value.strip_query, null)
}
}
}
}
dynamic "route_rules" {
for_each = (
try(path_matcher.value.route_rules, null) == null
? []
: path_matcher.value.route_rules
)
content {
priority = try(route_rules.value.priority, null)
service = try(
google_compute_backend_bucket.bucket[route_rules.value.service].id,
google_compute_backend_service.group[route_rules.value.service].id,
route_rules.value.service,
null
)
dynamic "header_action" {
for_each = (
try(path_matcher.value.header_action, null) == null
? []
: [path_matcher.value.header_action]
)
content {
request_headers_to_remove = try(header_action.value.request_headers_to_remove, null)
response_headers_to_remove = try(header_action.value.response_headers_to_remove, null)
dynamic "request_headers_to_add" {
for_each = (
try(header_action.value.request_headers_to_add, null) == null
? []
: [header_action.value.request_headers_to_add]
)
content {
header_name = try(request_headers_to_add.value.header_name, null)
header_value = try(request_headers_to_add.value.header_value, null)
replace = try(request_headers_to_add.value.replace, null)
}
}
dynamic "response_headers_to_add" {
for_each = (
try(header_action.response_headers_to_add, null) == null
? []
: [header_action.response_headers_to_add]
)
content {
header_name = try(response_headers_to_add.value.header_name, null)
header_value = try(response_headers_to_add.value.header_value, null)
replace = try(response_headers_to_add.value.replace, null)
}
}
}
}
dynamic "match_rules" {
for_each = (
try(path_matcher.value.match_rules, null) == null
? []
: path_matcher.value.match_rules
)
content {
full_path_match = try(match_rules.value.full_path_match, null) # Must be between 1 and 1024 characters
ignore_case = try(match_rules.value.ignore_case, null)
prefix_match = try(match_rules.value.prefix_match, null)
regex_match = try(match_rules.value.regex_match, null)
dynamic "header_matches" {
for_each = (
try(match_rules.value.header_matches, null) == null
? []
: [match_rules.value.header_matches]
)
content {
exact_match = try(header_matches.value.exact_match, null)
header_name = try(header_matches.value.header_name, null)
invert_match = try(header_matches.value.invert_match, null)
prefix_match = try(header_matches.value.prefix_match, null)
present_match = try(header_matches.value.present_match, null)
regex_match = try(header_matches.value.regex_match, null)
suffix_match = try(header_matches.value, null)
dynamic "range_match" {
for_each = try(header_matches.value.range_match, null) == null ? [] : [header_matches.value.range_match]
content {
range_end = try(range_match.value.range_end, null)
range_start = try(range_match.value.range_start, null)
}
}
}
}
dynamic "metadata_filters" {
for_each = (
try(match_rules.value.metadata_filters, null) == null
? []
: [match_rules.value.metadata_filters]
)
content {
# Valid values at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#filter_match_criteria
filter_match_criteria = try(metadata_filters.value.filter_match_criteria, null)
dynamic "filter_labels" {
for_each = (
try(metadata_filters.value.filter_labels, null) == null
? []
: metadata_filters.value.filter_labels
)
content {
name = try(filter_labels.value.name, null) # Must be between 1 and 1024 characters
value = try(filter_labels.value.value, null) # Must be between 1 and 1024 characters
}
}
}
}
dynamic "query_parameter_matches" {
for_each = (
try(match_rules.value.query_parameter_matches, null) == null
? []
: [match_rules.value.query_parameter_matches]
)
iterator = query
content {
exact_match = try(query.value.exact_match, null)
name = try(query.value.name, null)
present_match = try(query.value.present_match, null)
regex_match = try(query.value.regex_match, null)
}
}
}
}
dynamic "route_action" {
for_each = (
try(route_rules.value.route_action, null) == null
? []
: [route_rules.value.route_action]
)
content {
dynamic "cors_policy" {
for_each = (
try(route_action.value.cors_policy, null) == null
? []
: [route_action.value.cors_policy]
)
content {
allow_credentials = try(cors_policy.value.allow_credentials, null)
allow_headers = try(cors_policy.value.allow_headers, null)
allow_methods = try(cors_policy.value.allow_methods, null)
allow_origin_regexes = try(cors_policy.value.allow_origin_regexes, null)
allow_origins = try(cors_policy.value.allow_origins, null)
disabled = try(cors_policy.value.disabled, null)
expose_headers = try(cors_policy.value.expose_headers, null)
max_age = try(cors_policy.value.max_age, null)
}
}
dynamic "fault_injection_policy" {
for_each = (
try(route_action.value.fault_injection_policy, null) == null
? []
: [route_action.value.fault_injection_policy]
)
iterator = policy
content {
dynamic "abort" {
for_each = (
try(policy.value.abort, null) == null
? []
: [policy.value.abort]
)
content {
http_status = try(abort.value.http_status, null) # Must be between 200 and 599 inclusive
percentage = try(abort.value.percentage, null) # Must be between 0.0 and 100.0 inclusive
}
}
dynamic "delay" {
for_each = (
try(policy.value.delay, null) == null
? []
: [policy.value.delay]
)
content {
percentage = try(delay.value.percentage, null) # Must be between 0.0 and 100.0 inclusive
dynamic "fixed_delay" {
for_each = (
try(delay.value.fixed_delay, null) == null
? []
: [delay.value.fixed_delay]
)
content {
nanos = try(fixed_delay.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
seconds = try(fixed_delay.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
}
}
}
}
}
}
dynamic "request_mirror_policy" {
for_each = (
try(route_action.value.request_mirror_policy, null) == null
? []
: [route_action.value.request_mirror_policy]
)
iterator = policy
content {
backend_service = try(
google_compute_backend_bucket.bucket[policy.value.backend_service].id,
google_compute_backend_service.group[policy.value.backend_service].id,
policy.value.backend_service,
null
)
}
}
dynamic "retry_policy" {
for_each = (
try(route_action.value.retry_policy, null) == null
? []
: [route_action.value.retry_policy]
)
iterator = policy
content {
num_retries = try(policy.num_retries, null) # Must be > 0
# Valid values at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#retry_conditions
retry_conditions = try(policy.retry_conditions, null)
dynamic "per_try_timeout" {
for_each = (
try(policy.value.per_try_timeout, null) == null
? []
: [policy.value.per_try_timeout]
)
iterator = timeout
content {
nanos = try(timeout.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
seconds = try(timeout.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
}
}
}
}
dynamic "timeout" {
for_each = (
try(route_action.value.timeout, null) == null
? []
: [route_action.value.timeout]
)
content {
nanos = try(timeout.value.nanos, null) # Must be from 0 to 999,999,999 inclusive
seconds = try(timeout.value.seconds, null) # Must be from 0 to 315,576,000,000 inclusive
}
}
dynamic "url_rewrite" {
for_each = (
try(route_action.value.url_rewrite, null) == null
? []
: [route_action.value.url_rewrite]
)
content {
host_rewrite = try(url_rewrite.value.host_rewrite, null) # Must be between 1 and 255 characters
path_prefix_rewrite = try(url_rewrite.value.path_prefix_rewrite, null) # Must be between 1 and 1024 characters
}
}
dynamic "weighted_backend_services" {
for_each = (
try(route_action.value.weighted_backend_services, null) == null
? []
: [route_action.value.url_rewrite]
)
iterator = weighted
content {
weight = try(weighted.value.weigth, null)
backend_service = try(
google_compute_backend_bucket.bucket[weighted.value.backend_service].id,
google_compute_backend_service.group[weighted.value.backend_service].id,
weighted.value.backend_service,
null
)
dynamic "header_action" {
for_each = (
try(path_matcher.value.header_action, null) == null
? [] :
[path_matcher.value.header_action]
)
content {
request_headers_to_remove = try(header_action.value.request_headers_to_remove, null)
response_headers_to_remove = try(header_action.value.response_headers_to_remove, null)
dynamic "request_headers_to_add" {
for_each = (
try(header_action.value.request_headers_to_add, null) == null
? []
: [header_action.value.request_headers_to_add]
)
content {
header_name = try(request_headers_to_add.value.header_name, null)
header_value = try(request_headers_to_add.value.header_value, null)
replace = try(request_headers_to_add.value.replace, null)
}
}
dynamic "response_headers_to_add" {
for_each = (
try(header_action.response_headers_to_add, null) == null
? []
: [header_action.response_headers_to_add]
)
content {
header_name = try(response_headers_to_add.value.header_name, null)
header_value = try(response_headers_to_add.value.header_value, null)
replace = try(response_headers_to_add.value.replace, null)
}
}
}
}
}
}
}
}
dynamic "url_redirect" {
for_each = (
try(route_rules.value.url_redirect, null) == null
? []
: route_rules.value.url_redirect
)
content {
host_redirect = try(url_redirect.value.host_redirect, null) # Must be between 1 and 255 characters
https_redirect = try(url_redirect.value.https_redirect, null)
path_redirect = try(url_redirect.value.path_redirect, null)
prefix_redirect = try(url_redirect.value.prefix_redirect, null) # Must be between 1 and 1024 characters
# Valid valus at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#redirect_response_code
redirect_response_code = try(url_redirect.value.redirect_response_code, null)
strip_query = try(url_redirect.value.strip_query, null)
}
}
}
}
dynamic "default_url_redirect" {
for_each = (
try(path_matcher.value.default_url_redirect, null) == null
? []
: path_matcher.value.default_url_redirect
)
content {
host_redirect = try(default_url_redirect.value.host_redirect, null) # Must be between 1 and 255 characters
https_redirect = try(default_url_redirect.value.https_redirect, null)
path_redirect = try(default_url_redirect.value.path_redirect, null) # Must be between 1 and 1024 characters
prefix_redirect = try(default_url_redirect.value.prefix_redirect, null) # Must be between 1 and 1024 characters
# Valid values at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#redirect_response_code
redirect_response_code = try(default_url_redirect.value.redirect_response_code, null)
strip_query = try(default_url_redirect.value.strip_query, null)
}
}
}
}
# Up to 100 tests per url_map
dynamic "test" {
for_each = (
try(var.url_map_config.tests, null) == null
? []
: var.url_map_config.tests
)
content {
description = try(test.value.description, null)
host = try(test.value.host, null)
path = try(test.value.path, null)
service = try(
google_compute_backend_bucket.bucket[test.value.service].id,
google_compute_backend_service.group[test.value.service].id,
test.value.service,
null
)
}
}
dynamic "default_url_redirect" {
for_each = (
try(var.url_map_config.default_url_redirect, null) == null
? []
: [var.url_map_config.default_url_redirect]
)
content {
host_redirect = try(default_url_redirect.value.host_redirect, null) # Must be between 1 and 255 characters
https_redirect = try(default_url_redirect.value.https_redirect, null)
path_redirect = try(default_url_redirect.value.path_redirect, null) # Must be between 1 and 1024 characters
prefix_redirect = try(default_url_redirect.value.prefix_redirect, null) # Must be between 1 and 1024 characters
# Valid values at https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_url_map#redirect_response_code
redirect_response_code = try(default_url_redirect.value.redirect_response_code, null)
strip_query = try(default_url_redirect.value.strip_query, null)
}
}
}

View File

@ -40,18 +40,37 @@ locals {
}
resource "google_compute_target_http_proxy" "http" {
count = var.https ? 0 : 1
count = var.https ? 0 : (var.region == null ? 1 : 0)
name = var.name
project = var.project_id
description = "Terraform managed."
url_map = google_compute_url_map.url_map.id
url_map = google_compute_url_map.url_map.0.id
}
resource "google_compute_target_https_proxy" "https" {
count = var.https ? 1 : 0
count = var.https ? (var.region == null ? 1 : 0) : 0
name = var.name
project = var.project_id
description = "Terraform managed."
url_map = google_compute_url_map.url_map.id
url_map = google_compute_url_map.url_map.0.id
ssl_certificates = local.ssl_certificates
}
resource "google_compute_region_target_http_proxy" "http" {
count = var.https ? 0 : (var.region != null ? 1 : 0)
name = var.name
project = var.project_id
region = var.region
description = "Terraform managed."
url_map = google_compute_region_url_map.url_map.0.id
}
resource "google_compute_region_target_https_proxy" "https" {
count = var.https ? (var.region != null ? 1 : 0) : 0
name = var.name
project = var.project_id
region = var.region
description = "Terraform managed."
url_map = google_compute_region_url_map.url_map.0.id
ssl_certificates = local.ssl_certificates
}

View File

@ -45,6 +45,7 @@ locals {
}
resource "google_compute_url_map" "url_map" {
count = var.region == null ? 1 : 0
name = var.name
description = "Terraform managed."
project = var.project_id
@ -1180,3 +1181,4 @@ resource "google_compute_url_map" "url_map" {
}
}
}

View File

@ -24,6 +24,12 @@ variable "project_id" {
type = string
}
variable "region" {
description = "Create a regional load balancer in this region."
type = string
default = null
}
variable "health_checks_config_defaults" {
description = "Auto-created health check default configuration."
type = object({
@ -217,6 +223,27 @@ variable "global_forwarding_rule_config" {
}
}
variable "forwarding_rule_config" {
description = "Regional forwarding rule configurations."
type = object({
ip_protocol = string
ip_version = string
load_balancing_scheme = string
port_range = string
network_tier = string
network = string
})
default = {
load_balancing_scheme = "EXTERNAL_MANAGED"
ip_protocol = "TCP"
ip_version = "IPV4"
network_tier = "STANDARD"
network = "default"
# If not specified, 80 for https = false, 443 otherwise
port_range = null
}
}
variable "https" {
description = "Whether to enable HTTPS."
type = bool

View File

@ -18,6 +18,7 @@ module "test" {
source = "../../../../modules/net-glb"
project_id = "my-project"
name = "glb-test"
region = var.region
health_checks_config_defaults = var.health_checks_config_defaults
health_checks_config = var.health_checks_config
backend_services_config = var.backend_services_config
@ -28,4 +29,6 @@ module "test" {
target_proxy_https_config = var.target_proxy_https_config
reserve_ip_address = var.reserve_ip_address
global_forwarding_rule_config = var.global_forwarding_rule_config
forwarding_rule_config = var.forwarding_rule_config
}

View File

@ -14,6 +14,12 @@
* limitations under the License.
*/
variable "region" {
description = "Create a regional load balancer."
type = string
default = null
}
variable "health_checks_config_defaults" {
description = "Auto-created health check default configuration."
type = object({
@ -207,6 +213,27 @@ variable "global_forwarding_rule_config" {
}
}
variable "forwarding_rule_config" {
description = "Global forwarding rule configurations."
type = object({
ip_protocol = string
ip_version = string
load_balancing_scheme = string
port_range = string
network_tier = string
network = string
})
default = {
load_balancing_scheme = "EXTERNAL_MANAGED"
ip_protocol = "TCP"
ip_version = "IPV4"
# If not specified, 80 for https = false, 443 otherwise
port_range = null
network_tier = "STANDARD"
network = "default"
}
}
variable "https" {
description = "Whether to enable HTTPS."
type = bool

View File

@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
_BACKEND_BUCKET = '''{
my-bucket = {
bucket_config = {
@ -94,168 +93,211 @@ _TARGET_PROXY_HTTPS_CONFIG = '''{
def test_bucket(plan_runner):
"Tests a bucket backend service."
_, resources = plan_runner(backend_services_config=_BACKEND_BUCKET)
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
"Tests a bucket backend service."
_, resources = plan_runner(backend_services_config=_BACKEND_BUCKET)
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['load_balancing_scheme'] == 'EXTERNAL'
assert fwd_rule['port_range'] == '80'
assert fwd_rule['ip_protocol'] == 'TCP'
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['load_balancing_scheme'] == 'EXTERNAL'
assert fwd_rule['port_range'] == '80'
assert fwd_rule['ip_protocol'] == 'TCP'
bucket = resources['google_compute_backend_bucket']
assert bucket['name'] == _NAME + '-my-bucket'
assert bucket['enable_cdn'] is False
bucket = resources['google_compute_backend_bucket']
assert bucket['name'] == _NAME + '-my-bucket'
assert bucket['enable_cdn'] is False
assert 'google_compute_health_check' not in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_health_check' not in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_url_map' in resources
def test_group_default_hc(plan_runner):
"Tests a group backend service with no HC specified."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP)
assert len(resources) == 5
resources = dict((r['type'], r['values']) for r in resources)
"Tests a group backend service with no HC specified."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP)
assert len(resources) == 5
resources = dict((r['type'], r['values']) for r in resources)
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['load_balancing_scheme'] == 'EXTERNAL'
assert fwd_rule['port_range'] == '80'
assert fwd_rule['ip_protocol'] == 'TCP'
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['load_balancing_scheme'] == 'EXTERNAL'
assert fwd_rule['port_range'] == '80'
assert fwd_rule['ip_protocol'] == 'TCP'
group = resources['google_compute_backend_service']
assert len(group['backend']) == 1
assert group['backend'][0]['group'] == 'my_group'
group = resources['google_compute_backend_service']
assert len(group['backend']) == 1
assert group['backend'][0]['group'] == 'my_group'
health_check = resources['google_compute_health_check']
assert health_check['name'] == _NAME + '-default'
assert len(health_check['http_health_check']) > 0
assert len(health_check['https_health_check']) == 0
assert len(health_check['http2_health_check']) == 0
assert len(health_check['tcp_health_check']) == 0
assert health_check['http_health_check'][0]['port_specification'] == 'USE_SERVING_PORT'
assert health_check['http_health_check'][0]['proxy_header'] == 'NONE'
assert health_check['http_health_check'][0]['request_path'] == '/'
health_check = resources['google_compute_health_check']
assert health_check['name'] == _NAME + '-default'
assert len(health_check['http_health_check']) > 0
assert len(health_check['https_health_check']) == 0
assert len(health_check['http2_health_check']) == 0
assert len(health_check['tcp_health_check']) == 0
assert health_check['http_health_check'][0][
'port_specification'] == 'USE_SERVING_PORT'
assert health_check['http_health_check'][0]['proxy_header'] == 'NONE'
assert health_check['http_health_check'][0]['request_path'] == '/'
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
def test_group_default_hc_regional(plan_runner):
"Tests a group backend service with no HC specified."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP,
region="europe-west4")
assert len(resources) == 5
resources = dict((r['type'], r['values']) for r in resources)
fwd_rule = resources['google_compute_forwarding_rule']
assert fwd_rule['load_balancing_scheme'] == 'EXTERNAL_MANAGED'
assert fwd_rule['port_range'] == '80'
assert fwd_rule['ip_protocol'] == 'TCP'
group = resources['google_compute_region_backend_service']
assert len(group['backend']) == 1
assert group['backend'][0]['group'] == 'my_group'
health_check = resources['google_compute_region_health_check']
assert health_check['name'] == _NAME + '-default'
assert len(health_check['http_health_check']) > 0
assert len(health_check['https_health_check']) == 0
assert len(health_check['http2_health_check']) == 0
assert len(health_check['tcp_health_check']) == 0
assert health_check['http_health_check'][0][
'port_specification'] == 'USE_SERVING_PORT'
assert health_check['http_health_check'][0]['proxy_header'] == 'NONE'
assert health_check['http_health_check'][0]['request_path'] == '/'
assert 'google_compute_region_target_http_proxy' in resources
assert 'google_compute_region_target_https_proxy' not in resources
assert 'google_compute_region_url_map' in resources
def test_group_no_hc(plan_runner):
"Tests a group backend service without HCs (including no default HC)."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP,
health_checks_config_defaults='null')
"Tests a group backend service without HCs (including no default HC)."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP,
health_checks_config_defaults='null')
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_health_check' not in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_health_check' not in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
def test_group_existing_hc(plan_runner):
"Tests a group backend service with referencing an existing HC."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP_HC)
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
"Tests a group backend service with referencing an existing HC."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP_HC)
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_health_check' not in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_health_check' not in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
def test_group_existing_hc_regional(plan_runner):
"Tests a group backend service with referencing an existing HC."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP_HC,
region="europe-west4")
assert len(resources) == 4
resources = dict((r['type'], r['values']) for r in resources)
assert 'google_compute_region_backend_service' in resources
assert 'google_compute_forwarding_rule' in resources
assert 'google_compute_region_health_check' not in resources
assert 'google_compute_region_target_http_proxy' in resources
assert 'google_compute_region_target_https_proxy' not in resources
assert 'google_compute_region_url_map' in resources
def test_reserved_ip(plan_runner):
"Tests an IP reservation with a group backend service."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
reserve_ip_address="true"
)
assert len(resources) == 6
resources = dict((r['type'], r['values']) for r in resources)
"Tests an IP reservation with a group backend service."
_, resources = plan_runner(backend_services_config=_BACKEND_GROUP,
reserve_ip_address="true")
assert len(resources) == 6
resources = dict((r['type'], r['values']) for r in resources)
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_address' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_address' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_target_http_proxy' in resources
assert 'google_compute_target_https_proxy' not in resources
assert 'google_compute_url_map' in resources
def test_ssl_managed(plan_runner):
"Tests HTTPS and SSL managed certificates."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
https='true',
ssl_certificates_config=_SSL_CERTIFICATES_CONFIG_MANAGED,
target_proxy_https_config=_TARGET_PROXY_HTTPS_CONFIG
)
assert len(resources) == 6
resources = dict((r['type'], r['values']) for r in resources)
"Tests HTTPS and SSL managed certificates."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
https='true',
ssl_certificates_config=_SSL_CERTIFICATES_CONFIG_MANAGED,
target_proxy_https_config=_TARGET_PROXY_HTTPS_CONFIG)
assert len(resources) == 6
resources = dict((r['type'], r['values']) for r in resources)
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['port_range'] == '443'
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['port_range'] == '443'
ssl_cert = resources['google_compute_managed_ssl_certificate']
assert ssl_cert['type'] == "MANAGED"
assert ssl_cert['managed'][0]['domains'][0] == 'my-domain.com'
ssl_cert = resources['google_compute_managed_ssl_certificate']
assert ssl_cert['type'] == "MANAGED"
assert ssl_cert['managed'][0]['domains'][0] == 'my-domain.com'
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_ssl_certificate' not in resources
assert 'google_compute_target_http_proxy' not in resources
assert 'google_compute_target_https_proxy' in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_ssl_certificate' not in resources
assert 'google_compute_target_http_proxy' not in resources
assert 'google_compute_target_https_proxy' in resources
assert 'google_compute_url_map' in resources
def test_ssl_unmanaged(plan_runner):
"Tests HTTPS and SSL unmanaged certificates."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
https="true",
ssl_certificates_config=_SSL_CERTIFICATES_CONFIG_UNMANAGED,
target_proxy_https_config=_TARGET_PROXY_HTTPS_CONFIG
)
assert len(resources) == 6
resources = dict((r['type'], r['values']) for r in resources)
"Tests HTTPS and SSL unmanaged certificates."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
https="true",
ssl_certificates_config=_SSL_CERTIFICATES_CONFIG_UNMANAGED,
target_proxy_https_config=_TARGET_PROXY_HTTPS_CONFIG)
assert len(resources) == 6
resources = dict((r['type'], r['values']) for r in resources)
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['port_range'] == '443'
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['port_range'] == '443'
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_managed_ssl_certificate' not in resources
assert 'google_compute_ssl_certificate' in resources
assert 'google_compute_target_http_proxy' not in resources
assert 'google_compute_target_https_proxy' in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_managed_ssl_certificate' not in resources
assert 'google_compute_ssl_certificate' in resources
assert 'google_compute_target_http_proxy' not in resources
assert 'google_compute_target_https_proxy' in resources
assert 'google_compute_url_map' in resources
def test_ssl_existing_cert(plan_runner):
"Tests HTTPS and SSL existing certificate."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
https="true",
target_proxy_https_config=_TARGET_PROXY_HTTPS_CONFIG
)
assert len(resources) == 5
resources = dict((r['type'], r['values']) for r in resources)
"Tests HTTPS and SSL existing certificate."
_, resources = plan_runner(
backend_services_config=_BACKEND_GROUP,
https="true",
target_proxy_https_config=_TARGET_PROXY_HTTPS_CONFIG)
assert len(resources) == 5
resources = dict((r['type'], r['values']) for r in resources)
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['port_range'] == '443'
fwd_rule = resources['google_compute_global_forwarding_rule']
assert fwd_rule['port_range'] == '443'
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_managed_ssl_certificate' not in resources
assert 'google_compute_ssl_certificate' not in resources
assert 'google_compute_target_http_proxy' not in resources
assert 'google_compute_target_https_proxy' in resources
assert 'google_compute_url_map' in resources
assert 'google_compute_backend_service' in resources
assert 'google_compute_global_forwarding_rule' in resources
assert 'google_compute_managed_ssl_certificate' not in resources
assert 'google_compute_ssl_certificate' not in resources
assert 'google_compute_target_http_proxy' not in resources
assert 'google_compute_target_https_proxy' in resources
assert 'google_compute_url_map' in resources