diff --git a/modules/net-glb/README.md b/modules/net-glb/README.md index d754ae6609..c15229abdb 100644 --- a/modules/net-glb/README.md +++ b/modules/net-glb/README.md @@ -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. | google_compute_backend_bucket · google_compute_backend_service | | [global-forwarding-rule.tf](./global-forwarding-rule.tf) | Global address and forwarding rule. | google_compute_global_address · google_compute_global_forwarding_rule | -| [health-checks.tf](./health-checks.tf) | Health checks. | google_compute_health_check | +| [health-checks.tf](./health-checks.tf) | Health checks. | google_compute_health_check · google_compute_region_health_check | | [outputs.tf](./outputs.tf) | Module outputs. | | +| [regional-backend-services.tf](./regional-backend-services.tf) | Bucket and group backend services for regional load balancers. | google_compute_region_backend_service | +| [regional-forwarding-rule.tf](./regional-forwarding-rule.tf) | Global address and forwarding rule. | google_compute_address · google_compute_forwarding_rule | +| [regional-url-map.tf](./regional-url-map.tf) | regional URL maps. | google_compute_region_url_map | | [ssl-certificates.tf](./ssl-certificates.tf) | SSL certificates. | google_compute_managed_ssl_certificate · google_compute_ssl_certificate | -| [target-proxy.tf](./target-proxy.tf) | HTTP and HTTPS target proxies. | google_compute_target_http_proxy · google_compute_target_https_proxy | +| [target-proxy.tf](./target-proxy.tf) | HTTP and HTTPS target proxies. | google_compute_region_target_http_proxy · google_compute_region_target_https_proxy · google_compute_target_http_proxy · google_compute_target_https_proxy | | [url-map.tf](./url-map.tf) | URL maps. | google_compute_url_map | | [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. | string | ✓ | | | [project_id](variables.tf#L22) | Project id. | string | ✓ | | -| [backend_services_config](variables.tf#L56) | The backends services configuration. | map(object({…})) | | {} | -| [global_forwarding_rule_config](variables.tf#L202) | Global forwarding rule configurations. | object({…}) | | {…} | -| [health_checks_config](variables.tf#L45) | Custom health checks configuration. | map(object({…})) | | {} | -| [health_checks_config_defaults](variables.tf#L27) | Auto-created health check default configuration. | object({…}) | | {…} | -| [https](variables.tf#L220) | Whether to enable HTTPS. | bool | | false | -| [reserve_ip_address](variables.tf#L226) | Whether to reserve a static global IP address. | bool | | false | -| [ssl_certificates_config](variables.tf#L165) | The SSL certificate configuration. | map(object({…})) | | {} | -| [ssl_certificates_config_defaults](variables.tf#L178) | The SSL certificate default configuration. | object({…}) | | {…} | -| [target_proxy_https_config](variables.tf#L194) | The HTTPS target proxy configuration. | object({…}) | | null | -| [url_map_config](variables.tf#L151) | The url-map configuration. | object({…}) | | null | +| [backend_services_config](variables.tf#L62) | The backends services configuration. | map(object({…})) | | {} | +| [forwarding_rule_config](variables.tf#L226) | Regional forwarding rule configurations. | object({…}) | | {…} | +| [global_forwarding_rule_config](variables.tf#L208) | Global forwarding rule configurations. | object({…}) | | {…} | +| [health_checks_config](variables.tf#L51) | Custom health checks configuration. | map(object({…})) | | {} | +| [health_checks_config_defaults](variables.tf#L33) | Auto-created health check default configuration. | object({…}) | | {…} | +| [https](variables.tf#L247) | Whether to enable HTTPS. | bool | | false | +| [region](variables.tf#L27) | Create a regional load balancer in this region. | string | | null | +| [reserve_ip_address](variables.tf#L253) | Whether to reserve a static global IP address. | bool | | false | +| [ssl_certificates_config](variables.tf#L171) | The SSL certificate configuration. | map(object({…})) | | {} | +| [ssl_certificates_config_defaults](variables.tf#L184) | The SSL certificate default configuration. | object({…}) | | {…} | +| [target_proxy_https_config](variables.tf#L200) | The HTTPS target proxy configuration. | object({…}) | | null | +| [url_map_config](variables.tf#L157) | The url-map configuration. | object({…}) | | null | ## 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. | | diff --git a/modules/net-glb/backend-services.tf b/modules/net-glb/backend-services.tf index 9bb925019d..3ca93da872 100644 --- a/modules/net-glb/backend-services.tf +++ b/modules/net-glb/backend-services.tf @@ -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" { } } } + diff --git a/modules/net-glb/global-forwarding-rule.tf b/modules/net-glb/global-forwarding-rule.tf index b4d525c9f6..54c268f01d 100644 --- a/modules/net-glb/global-forwarding-rule.tf +++ b/modules/net-glb/global-forwarding-rule.tf @@ -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 diff --git a/modules/net-glb/health-checks.tf b/modules/net-glb/health-checks.tf index 88a2954855..0c0aad6323 100644 --- a/modules/net-glb/health-checks.tf +++ b/modules/net-glb/health-checks.tf @@ -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 + } + } +} diff --git a/modules/net-glb/outputs.tf b/modules/net-glb/outputs.tf index 490378f21b..8e2e4e5806 100644 --- a/modules/net-glb/outputs.tf +++ b/modules/net-glb/outputs.tf @@ -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 } diff --git a/modules/net-glb/regional-forwarding-rule.tf b/modules/net-glb/regional-forwarding-rule.tf new file mode 100644 index 0000000000..5f4e3d71ed --- /dev/null +++ b/modules/net-glb/regional-forwarding-rule.tf @@ -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 +} diff --git a/modules/net-glb/regional-url-map.tf b/modules/net-glb/regional-url-map.tf new file mode 100644 index 0000000000..19600c2911 --- /dev/null +++ b/modules/net-glb/regional-url-map.tf @@ -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 = var.region != null ? 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 + ) : null + + # If no backend services are specified, + # the first backend service defined is associated + regional_default_service = var.region != null ? ( + 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 + ) : 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) + } + } +} diff --git a/modules/net-glb/target-proxy.tf b/modules/net-glb/target-proxy.tf index c3ede2282b..ddfbe454fc 100644 --- a/modules/net-glb/target-proxy.tf +++ b/modules/net-glb/target-proxy.tf @@ -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 } diff --git a/modules/net-glb/url-map.tf b/modules/net-glb/url-map.tf index 90cb44e34e..d81e049bde 100644 --- a/modules/net-glb/url-map.tf +++ b/modules/net-glb/url-map.tf @@ -22,16 +22,16 @@ locals { # 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. - _default_service = try( + _default_service = var.region == null ? try( google_compute_backend_bucket.bucket[var.url_map_config.default_service].id, google_compute_backend_service.group[var.url_map_config.default_service].id, var.url_map_config.default_service, null - ) + ) : null # If no backend services are specified, # the first backend service defined is associated - default_service = ( + default_service = var.region == null ? ( try(local._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 @@ -41,10 +41,11 @@ locals { null ) : null - ) + ) : null } 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" { } } } + diff --git a/modules/net-glb/variables.tf b/modules/net-glb/variables.tf index a53c113b3e..3260a9237d 100644 --- a/modules/net-glb/variables.tf +++ b/modules/net-glb/variables.tf @@ -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 diff --git a/tests/modules/net_glb/fixture/main.tf b/tests/modules/net_glb/fixture/main.tf index 544804d020..b2c68e035f 100644 --- a/tests/modules/net_glb/fixture/main.tf +++ b/tests/modules/net_glb/fixture/main.tf @@ -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 } + diff --git a/tests/modules/net_glb/fixture/variables.tf b/tests/modules/net_glb/fixture/variables.tf index 0067cce544..6b8184055b 100644 --- a/tests/modules/net_glb/fixture/variables.tf +++ b/tests/modules/net_glb/fixture/variables.tf @@ -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 diff --git a/tests/modules/net_glb/test_plan.py b/tests/modules/net_glb/test_plan.py index 802b083f58..758ea50876 100644 --- a/tests/modules/net_glb/test_plan.py +++ b/tests/modules/net_glb/test_plan.py @@ -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 @@ 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) - - 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' - - 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 + "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' + + 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'] == '/' + + 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) - - 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 + "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 + + +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) - - 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 + "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 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) - - 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' - - 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 + "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' + + 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 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) - - 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 + "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' + + 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) - - 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 + "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' + + 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