Rename network load balancer modules (#1466)

* update LB modules to new names

* update LB modules names

* update test paths
This commit is contained in:
Ludovico Magnocavallo
2023-06-26 09:50:10 +02:00
committed by GitHub
parent 4b6552a6f6
commit 638841c8d1
106 changed files with 189 additions and 166 deletions

3
modules/net-lb-app-ext/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*backup
*tfstate
tfvars

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,262 @@
/**
* 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 Backend service resources.
locals {
group_ids = merge(
{
for k, v in google_compute_instance_group.default : k => v.id
},
{
for k, v in google_compute_global_network_endpoint_group.default : k => v.id
},
{
for k, v in google_compute_network_endpoint_group.default : k => v.id
},
{
for k, v in google_compute_region_network_endpoint_group.psc : k => v.id
},
{
for k, v in google_compute_region_network_endpoint_group.serverless : k => v.id
}
)
hc_ids = {
for k, v in google_compute_health_check.default : k => v.id
}
}
# google_compute_backend_bucket
resource "google_compute_backend_service" "default" {
provider = google-beta
for_each = var.backend_service_configs
project = (
each.value.project_id == null
? var.project_id
: each.value.project_id
)
name = "${var.name}-${each.key}"
description = var.description
affinity_cookie_ttl_sec = each.value.affinity_cookie_ttl_sec
compression_mode = each.value.compression_mode
connection_draining_timeout_sec = each.value.connection_draining_timeout_sec
custom_request_headers = each.value.custom_request_headers
custom_response_headers = each.value.custom_response_headers
enable_cdn = each.value.enable_cdn
health_checks = length(each.value.health_checks) == 0 ? null : [
for k in each.value.health_checks : lookup(local.hc_ids, k, k)
]
load_balancing_scheme = var.use_classic_version ? "EXTERNAL" : "EXTERNAL_MANAGED"
port_name = (
each.value.port_name == null
? lower(each.value.protocol == null ? var.protocol : each.value.protocol)
: each.value.port_name
)
protocol = (
each.value.protocol == null ? var.protocol : each.value.protocol
)
security_policy = each.value.security_policy
session_affinity = each.value.session_affinity
timeout_sec = each.value.timeout_sec
dynamic "backend" {
for_each = { for b in coalesce(each.value.backends, []) : b.backend => b }
content {
group = lookup(local.group_ids, backend.key, backend.key)
balancing_mode = backend.value.balancing_mode # UTILIZATION, RATE
capacity_scaler = backend.value.capacity_scaler
description = backend.value.description
max_connections = try(
backend.value.max_connections.per_group, null
)
max_connections_per_endpoint = try(
backend.value.max_connections.per_endpoint, null
)
max_connections_per_instance = try(
backend.value.max_connections.per_instance, null
)
max_rate = try(
backend.value.max_rate.per_group, null
)
max_rate_per_endpoint = try(
backend.value.max_rate.per_endpoint, null
)
max_rate_per_instance = try(
backend.value.max_rate.per_instance, null
)
max_utilization = backend.value.max_utilization
}
}
dynamic "cdn_policy" {
for_each = (
each.value.cdn_policy == null ? [] : [each.value.cdn_policy]
)
iterator = cdn
content {
cache_mode = cdn.value.cache_mode
client_ttl = cdn.value.client_ttl
default_ttl = cdn.value.default_ttl
max_ttl = cdn.value.max_ttl
negative_caching = cdn.value.negative_caching
serve_while_stale = cdn.value.serve_while_stale
signed_url_cache_max_age_sec = cdn.value.signed_url_cache_max_age_sec
dynamic "cache_key_policy" {
for_each = (
cdn.value.cache_key_policy == null
? []
: [cdn.value.cache_key_policy]
)
iterator = ck
content {
include_host = ck.value.include_host
include_named_cookies = ck.value.include_named_cookies
include_protocol = ck.value.include_protocol
include_query_string = ck.value.include_query_string
query_string_blacklist = ck.value.query_string_blacklist
query_string_whitelist = ck.value.query_string_whitelist
}
}
dynamic "negative_caching_policy" {
for_each = (
cdn.value.negative_caching_policy == null
? []
: [cdn.value.negative_caching_policy]
)
iterator = nc
content {
code = nc.value.code
ttl = nc.value.ttl
}
}
}
}
dynamic "circuit_breakers" {
for_each = (
each.value.circuit_breakers == null ? [] : [each.value.circuit_breakers]
)
iterator = cb
content {
max_connections = cb.value.max_connections
max_pending_requests = cb.value.max_pending_requests
max_requests = cb.value.max_requests
max_requests_per_connection = cb.value.max_requests_per_connection
max_retries = cb.value.max_retries
dynamic "connect_timeout" {
for_each = (
cb.value.connect_timeout == null ? [] : [cb.value.connect_timeout]
)
content {
seconds = connect_timeout.value.seconds
nanos = connect_timeout.value.nanos
}
}
}
}
dynamic "consistent_hash" {
for_each = (
each.value.consistent_hash == null ? [] : [each.value.consistent_hash]
)
iterator = ch
content {
http_header_name = ch.value.http_header_name
minimum_ring_size = ch.value.minimum_ring_size
dynamic "http_cookie" {
for_each = ch.value.http_cookie == null ? [] : [ch.value.http_cookie]
content {
name = http_cookie.value.name
path = http_cookie.value.path
dynamic "ttl" {
for_each = (
http_cookie.value.ttl == null ? [] : [http_cookie.value.ttl]
)
content {
seconds = ttl.value.seconds
nanos = ttl.value.nanos
}
}
}
}
}
}
dynamic "iap" {
for_each = each.value.iap_config == null ? [] : [each.value.iap_config]
content {
oauth2_client_id = iap.value.oauth2_client_id
oauth2_client_secret = iap.value.oauth2_client_secret
oauth2_client_secret_sha256 = iap.value.oauth2_client_secret_sha256
}
}
dynamic "log_config" {
for_each = each.value.log_sample_rate == null ? [] : [""]
content {
enable = true
sample_rate = each.value.log_sample_rate
}
}
dynamic "outlier_detection" {
for_each = (
each.value.outlier_detection == null ? [] : [each.value.outlier_detection]
)
iterator = od
content {
consecutive_errors = od.value.consecutive_errors
consecutive_gateway_failure = od.value.consecutive_gateway_failure
enforcing_consecutive_errors = od.value.enforcing_consecutive_errors
enforcing_consecutive_gateway_failure = od.value.enforcing_consecutive_gateway_failure
enforcing_success_rate = od.value.enforcing_success_rate
max_ejection_percent = od.value.max_ejection_percent
success_rate_minimum_hosts = od.value.success_rate_minimum_hosts
success_rate_request_volume = od.value.success_rate_request_volume
success_rate_stdev_factor = od.value.success_rate_stdev_factor
dynamic "base_ejection_time" {
for_each = (
od.value.base_ejection_time == null ? [] : [od.value.base_ejection_time]
)
content {
seconds = base_ejection_time.value.seconds
nanos = base_ejection_time.value.nanos
}
}
dynamic "interval" {
for_each = (
od.value.interval == null ? [] : [od.value.interval]
)
content {
seconds = interval.value.seconds
nanos = interval.value.nanos
}
}
}
}
dynamic "security_settings" {
for_each = (
each.value.security_settings == null ? [] : [each.value.security_settings]
)
iterator = ss
content {
client_tls_policy = ss.value.client_tls_policy
subject_alt_names = ss.value.subject_alt_names
}
}
}

View File

@@ -0,0 +1,98 @@
/**
* 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 Backend groups and backend buckets resources.
resource "google_compute_backend_bucket" "default" {
for_each = var.backend_buckets_config
project = var.project_id
name = "${var.name}-${each.key}"
bucket_name = each.value.bucket_name
compression_mode = each.value.compression_mode
custom_response_headers = each.value.custom_response_headers
description = each.value.description
edge_security_policy = each.value.edge_security_policy
enable_cdn = each.value.enable_cdn
dynamic "cdn_policy" {
for_each = each.value.cdn_policy == null ? [] : [each.value.cdn_policy]
iterator = p
content {
cache_mode = p.value.cache_mode
client_ttl = p.value.client_ttl
default_ttl = p.value.default_ttl
max_ttl = p.value.max_ttl
negative_caching = p.value.negative_caching
request_coalescing = p.value.request_coalescing
serve_while_stale = p.value.serve_while_stale
signed_url_cache_max_age_sec = p.value.signed_url_cache_max_age_sec
dynamic "bypass_cache_on_request_headers" {
for_each = (
p.value.bypass_cache_on_request_headers == null
? []
: [p.value.bypass_cache_on_request_headers]
)
iterator = h
content {
header_name = h.value
}
}
dynamic "cache_key_policy" {
for_each = (
p.value.cache_key_policy == null ? [] : [p.value.cache_key_policy]
)
iterator = ckp
content {
include_http_headers = ckp.value.include_http_headers
query_string_whitelist = ckp.value.query_string_whitelist
}
}
dynamic "negative_caching_policy" {
for_each = (
p.value.negative_caching_policy == null
? []
: [p.value.negative_caching_policy]
)
iterator = ncp
content {
code = ncp.value.code
ttl = ncp.value.ttl
}
}
}
}
}
resource "google_compute_instance_group" "default" {
for_each = var.group_configs
project = (
each.value.project_id == null
? var.project_id
: each.value.project_id
)
zone = each.value.zone
name = "${var.name}-${each.key}"
description = var.description
instances = each.value.instances
dynamic "named_port" {
for_each = each.value.named_ports
content {
name = named_port.key
port = named_port.value
}
}
}

View File

@@ -0,0 +1,113 @@
/**
* 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 Health check resource.
resource "google_compute_health_check" "default" {
provider = google-beta
for_each = var.health_check_configs
project = (
each.value.project_id == null
? var.project_id
: each.value.project_id
)
name = "${var.name}-${each.key}"
description = each.value.description
check_interval_sec = each.value.check_interval_sec
healthy_threshold = each.value.healthy_threshold
timeout_sec = each.value.timeout_sec
unhealthy_threshold = each.value.unhealthy_threshold
dynamic "grpc_health_check" {
for_each = try(each.value.grpc, null) != null ? [""] : []
content {
port = each.value.grpc.port
port_name = each.value.grpc.port_name
port_specification = each.value.grpc.port_specification
grpc_service_name = each.value.grpc.service_name
}
}
dynamic "http_health_check" {
for_each = try(each.value.http, null) != null ? [""] : []
content {
host = each.value.http.host
port = each.value.http.port
port_name = each.value.http.port_name
port_specification = each.value.http.port_specification
proxy_header = each.value.http.proxy_header
request_path = each.value.http.request_path
response = each.value.http.response
}
}
dynamic "http2_health_check" {
for_each = try(each.value.http2, null) != null ? [""] : []
content {
host = each.value.http2.host
port = each.value.http2.port
port_name = each.value.http2.port_name
port_specification = each.value.http2.port_specification
proxy_header = each.value.http2.proxy_header
request_path = each.value.http2.request_path
response = each.value.http2.response
}
}
dynamic "https_health_check" {
for_each = try(each.value.https, null) != null ? [""] : []
content {
host = each.value.https.host
port = each.value.https.port
port_name = each.value.https.port_name
port_specification = each.value.https.port_specification
proxy_header = each.value.https.proxy_header
request_path = each.value.https.request_path
response = each.value.https.response
}
}
dynamic "ssl_health_check" {
for_each = try(each.value.ssl, null) != null ? [""] : []
content {
port = each.value.ssl.port
port_name = each.value.ssl.port_name
port_specification = each.value.ssl.port_specification
proxy_header = each.value.ssl.proxy_header
request = each.value.ssl.request
response = each.value.ssl.response
}
}
dynamic "tcp_health_check" {
for_each = try(each.value.tcp, null) != null ? [""] : []
content {
port = each.value.tcp.port
port_name = each.value.tcp.port_name
port_specification = each.value.tcp.port_specification
proxy_header = each.value.tcp.proxy_header
request = each.value.tcp.request
response = each.value.tcp.response
}
}
dynamic "log_config" {
for_each = try(each.value.enable_logging, null) == true ? [""] : []
content {
enable = true
}
}
}

View File

@@ -0,0 +1,91 @@
/**
* 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.
*/
locals {
fwd_rule_ports = (
var.protocol == "HTTPS" ? [443] : coalesce(var.ports, [80])
)
fwd_rule_target = (
var.protocol == "HTTPS"
? google_compute_target_https_proxy.default.0.id
: google_compute_target_http_proxy.default.0.id
)
proxy_ssl_certificates = concat(
coalesce(var.ssl_certificates.certificate_ids, []),
[for k, v in google_compute_ssl_certificate.default : v.id],
[for k, v in google_compute_managed_ssl_certificate.default : v.id]
)
}
resource "google_compute_global_forwarding_rule" "default" {
provider = google-beta
project = var.project_id
name = var.name
description = var.description
ip_address = var.address
ip_protocol = "TCP"
load_balancing_scheme = (
var.use_classic_version ? "EXTERNAL" : "EXTERNAL_MANAGED"
)
port_range = join(",", local.fwd_rule_ports)
labels = var.labels
target = local.fwd_rule_target
}
# certificates
resource "google_compute_ssl_certificate" "default" {
for_each = var.ssl_certificates.create_configs
project = var.project_id
name = "${var.name}-${each.key}"
certificate = trimspace(each.value.certificate)
private_key = trimspace(each.value.private_key)
}
resource "google_compute_managed_ssl_certificate" "default" {
for_each = var.ssl_certificates.managed_configs
project = var.project_id
name = "${var.name}-${each.key}"
description = each.value.description
managed {
domains = each.value.domains
}
lifecycle {
create_before_destroy = true
}
}
# proxies
resource "google_compute_target_http_proxy" "default" {
count = var.protocol == "HTTPS" ? 0 : 1
project = var.project_id
name = var.name
description = var.description
url_map = google_compute_url_map.default.id
}
resource "google_compute_target_https_proxy" "default" {
count = var.protocol == "HTTPS" ? 1 : 0
project = var.project_id
name = var.name
description = var.description
certificate_map = var.https_proxy_config.certificate_map
quic_override = var.https_proxy_config.quic_override
ssl_certificates = local.proxy_ssl_certificates
ssl_policy = var.https_proxy_config.ssl_policy
url_map = google_compute_url_map.default.id
}

View File

@@ -0,0 +1,159 @@
/**
* 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 NEG resources.
locals {
_neg_endpoints_global = flatten([
for k, v in local.neg_global : [
for kk, vv in v.internet.endpoints : merge(vv, {
key = "${k}-${kk}", neg = k, use_fqdn = v.internet.use_fqdn
})
]
])
_neg_endpoints_zonal = flatten([
for k, v in local.neg_zonal : [
for kk, vv in v.endpoints : merge(vv, {
key = "${k}-${kk}", neg = k, zone = v.zone
})
]
])
neg_endpoints_global = {
for v in local._neg_endpoints_global : (v.key) => v
}
neg_endpoints_zonal = {
for v in local._neg_endpoints_zonal : (v.key) => v
}
neg_global = {
for k, v in var.neg_configs :
k => v if v.internet != null
}
neg_regional_psc = {
for k, v in var.neg_configs :
k => v if v.psc != null
}
neg_regional_serverless = {
for k, v in var.neg_configs :
k => v if v.cloudrun != null || v.cloudfunction != null
}
neg_zonal = {
# we need to rebuild new objects as we cannot merge different types
for k, v in var.neg_configs : k => {
description = v.description
endpoints = v.gce != null ? v.gce.endpoints : v.hybrid.endpoints
network = v.gce != null ? v.gce.network : v.hybrid.network
subnetwork = v.gce != null ? v.gce.subnetwork : null
type = v.gce != null ? "GCE_VM_IP_PORT" : "NON_GCP_PRIVATE_IP_PORT"
zone = v.gce != null ? v.gce.zone : v.hybrid.zone
} if v.gce != null || v.hybrid != null
}
}
resource "google_compute_global_network_endpoint_group" "default" {
for_each = local.neg_global
project = var.project_id
name = "${var.name}-${each.key}"
# re-enable once provider properly supports this
# default_port = each.value.default_port
description = coalesce(each.value.description, var.description)
network_endpoint_type = (
each.value.internet.use_fqdn ? "INTERNET_FQDN_PORT" : "INTERNET_IP_PORT"
)
}
resource "google_compute_global_network_endpoint" "default" {
for_each = local.neg_endpoints_global
project = (
google_compute_global_network_endpoint_group.default[each.value.neg].project
)
global_network_endpoint_group = (
google_compute_global_network_endpoint_group.default[each.value.neg].name
)
fqdn = each.value.use_fqdn ? each.value.destination : null
ip_address = each.value.use_fqdn ? null : each.value.destination
port = each.value.port
}
resource "google_compute_network_endpoint_group" "default" {
for_each = local.neg_zonal
project = var.project_id
zone = each.value.zone
name = "${var.name}-${each.key}"
# re-enable once provider properly supports this
# default_port = each.value.default_port
description = coalesce(each.value.description, var.description)
network_endpoint_type = each.value.type
network = each.value.network
subnetwork = (
each.value.type == "NON_GCP_PRIVATE_IP_PORT"
? null
: each.value.subnetwork
)
}
resource "google_compute_network_endpoint" "default" {
for_each = local.neg_endpoints_zonal
project = (
google_compute_network_endpoint_group.default[each.value.neg].project
)
network_endpoint_group = (
google_compute_network_endpoint_group.default[each.value.neg].name
)
instance = try(each.value.instance, null)
ip_address = each.value.ip_address
port = each.value.port
zone = each.value.zone
}
resource "google_compute_region_network_endpoint_group" "psc" {
for_each = local.neg_regional_psc
project = var.project_id
region = each.value.psc.region
name = "${var.name}-${each.key}"
description = coalesce(each.value.description, var.description)
network_endpoint_type = "PRIVATE_SERVICE_CONNECT"
psc_target_service = each.value.psc.target_service
network = each.value.psc.network
subnetwork = each.value.psc.subnetwork
}
resource "google_compute_region_network_endpoint_group" "serverless" {
for_each = local.neg_regional_serverless
project = var.project_id
region = try(
each.value.cloudrun.region, each.value.cloudfunction.region, null
)
name = "${var.name}-${each.key}"
description = coalesce(each.value.description, var.description)
network_endpoint_type = "SERVERLESS"
dynamic "cloud_function" {
for_each = each.value.cloudfunction == null ? [] : [""]
content {
function = each.value.cloudfunction.target_function
url_mask = each.value.cloudfunction.target_urlmask
}
}
dynamic "cloud_run" {
for_each = each.value.cloudrun == null ? [] : [""]
content {
service = try(each.value.cloudrun.target_service.name, null)
tag = try(each.value.cloudrun.target_service.tag, null)
url_mask = each.value.cloudrun.target_urlmask
}
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.
*/
output "address" {
description = "Forwarding rule address."
value = google_compute_global_forwarding_rule.default.ip_address
}
output "backend_service_ids" {
description = "Backend service resources."
value = {
for k, v in google_compute_backend_service.default : k => v.id
}
}
output "backend_service_names" {
description = "Backend service resource names."
value = {
for k, v in google_compute_backend_service.default : k => v.name
}
}
output "forwarding_rule" {
description = "Forwarding rule resource."
value = google_compute_global_forwarding_rule.default
}
output "group_ids" {
description = "Autogenerated instance group ids."
value = {
for k, v in google_compute_instance_group.default : k => v.id
}
}
output "health_check_ids" {
description = "Autogenerated health check ids."
value = {
for k, v in google_compute_health_check.default : k => v.id
}
}
output "id" {
description = "Fully qualified forwarding rule id."
value = google_compute_global_forwarding_rule.default.id
}
output "neg_ids" {
description = "Autogenerated network endpoint group ids."
value = {
for k, v in google_compute_network_endpoint_group.default : k => v.id
}
}

View File

@@ -0,0 +1,952 @@
/**
* 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 URL map resources.
locals {
backend_ids = merge(
{ for k, v in google_compute_backend_service.default : k => v.id },
{ for k, v in google_compute_backend_bucket.default : k => v.id }
)
}
resource "google_compute_url_map" "default" {
provider = google-beta
project = var.project_id
name = var.name
description = var.description
default_service = (
var.urlmap_config.default_service == null ? null : lookup(
local.backend_ids,
var.urlmap_config.default_service,
var.urlmap_config.default_service
)
)
dynamic "default_route_action" {
for_each = (
var.urlmap_config.default_route_action == null
? []
: [var.urlmap_config.default_route_action]
)
iterator = route_action
content {
dynamic "cors_policy" {
for_each = (
route_action.value.cors_policy == null
? []
: [route_action.value.cors_policy]
)
content {
allow_credentials = cors_policy.value.allow_credentials
allow_headers = cors_policy.value.allow_headers
allow_methods = cors_policy.value.allow_methods
allow_origin_regexes = cors_policy.value.allow_origin_regexes
allow_origins = cors_policy.value.allow_origins
disabled = cors_policy.value.disabled
expose_headers = cors_policy.value.expose_headers
max_age = cors_policy.value.max_age
}
}
dynamic "fault_injection_policy" {
for_each = (
route_action.value.fault_injection_policy == null
? []
: [route_action.value.fault_injection_policy]
)
content {
dynamic "abort" {
for_each = (
fault_injection_policy.value.abort == null
? []
: [fault_injection_policy.value.abort]
)
content {
http_status = abort.value.status
percentage = abort.value.percentage
}
}
dynamic "delay" {
for_each = (
fault_injection_policy.value.delay == null
? []
: [fault_injection_policy.value.delay]
)
content {
percentage = delay.value.percentage
fixed_delay {
nanos = delay.value.fixed.nanos
seconds = delay.value.fixed.seconds
}
}
}
}
}
dynamic "request_mirror_policy" {
for_each = (
route_action.value.request_mirror_backend == null
? []
: [""]
)
content {
backend_service = lookup(
local.backend_ids,
route_action.value.request_mirror_backend,
route_action.value.request_mirror_backend
)
}
}
dynamic "retry_policy" {
for_each = (
route_action.value.retry_policy == null
? []
: [route_action.value.retry_policy]
)
content {
num_retries = retry_policy.value.num_retries
retry_conditions = retry_policy.value.retry_conditions
dynamic "per_try_timeout" {
for_each = (
retry_policy.value.per_try_timeout == null
? []
: [retry_policy.value.per_try_timeout]
)
content {
nanos = per_try_timeout.value.nanos
seconds = per_try_timeout.value.seconds
}
}
}
}
dynamic "timeout" {
for_each = (
route_action.value.timeout == null
? []
: [route_action.value.timeout]
)
content {
nanos = timeout.value.nanos
seconds = timeout.value.seconds
}
}
dynamic "url_rewrite" {
for_each = (
route_action.value.url_rewrite == null
? []
: [route_action.value.url_rewrite]
)
content {
host_rewrite = url_rewrite.value.host
path_prefix_rewrite = url_rewrite.value.path_prefix
}
}
dynamic "weighted_backend_services" {
for_each = coalesce(
route_action.value.weighted_backend_services, {}
)
iterator = service
content {
backend_service = lookup(
local.backend_ids, service.key, service.key
)
weight = service.value.weight
dynamic "header_action" {
for_each = (
service.value.header_action == null
? []
: [service.value.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
}
}
}
}
dynamic "default_url_redirect" {
for_each = (
var.urlmap_config.default_url_redirect == null
? []
: [var.urlmap_config.default_url_redirect]
)
iterator = r
content {
host_redirect = r.value.host
https_redirect = r.value.https
path_redirect = r.value.path
prefix_redirect = r.value.prefix
redirect_response_code = r.value.response_code
strip_query = r.value.strip_query
}
}
dynamic "header_action" {
for_each = (
var.urlmap_config.header_action == null
? []
: [var.urlmap_config.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
dynamic "host_rule" {
for_each = coalesce(var.urlmap_config.host_rules, [])
iterator = r
content {
hosts = r.value.hosts
path_matcher = r.value.path_matcher
description = r.value.description
}
}
dynamic "path_matcher" {
for_each = coalesce(var.urlmap_config.path_matchers, {})
iterator = m
content {
default_service = m.value.default_service == null ? null : lookup(
local.backend_ids, m.value.default_service, m.value.default_service
)
description = m.value.description
name = m.key
dynamic "default_route_action" {
for_each = (
m.value.default_route_action == null
? []
: [m.value.default_route_action]
)
iterator = route_action
content {
dynamic "cors_policy" {
for_each = (
route_action.value.cors_policy == null
? []
: [route_action.value.cors_policy]
)
content {
allow_credentials = cors_policy.value.allow_credentials
allow_headers = cors_policy.value.allow_headers
allow_methods = cors_policy.value.allow_methods
allow_origin_regexes = cors_policy.value.allow_origin_regexes
allow_origins = cors_policy.value.allow_origins
disabled = cors_policy.value.disabled
expose_headers = cors_policy.value.expose_headers
max_age = cors_policy.value.max_age
}
}
dynamic "fault_injection_policy" {
for_each = (
route_action.value.fault_injection_policy == null
? []
: [route_action.value.fault_injection_policy]
)
content {
dynamic "abort" {
for_each = (
fault_injection_policy.value.abort == null
? []
: [fault_injection_policy.value.abort]
)
content {
http_status = abort.value.status
percentage = abort.value.percentage
}
}
dynamic "delay" {
for_each = (
fault_injection_policy.value.delay == null
? []
: [fault_injection_policy.value.delay]
)
content {
percentage = delay.value.percentage
fixed_delay {
nanos = delay.value.fixed.nanos
seconds = delay.value.fixed.seconds
}
}
}
}
}
dynamic "request_mirror_policy" {
for_each = (
route_action.value.request_mirror_backend == null
? []
: [""]
)
content {
backend_service = lookup(
local.backend_ids,
route_action.value.request_mirror_backend,
route_action.value.request_mirror_backend
)
}
}
dynamic "retry_policy" {
for_each = (
route_action.value.retry_policy == null
? []
: [route_action.value.retry_policy]
)
content {
num_retries = retry_policy.value.num_retries
retry_conditions = retry_policy.value.retry_conditions
dynamic "per_try_timeout" {
for_each = (
retry_policy.value.per_try_timeout == null
? []
: [retry_policy.value.per_try_timeout]
)
content {
nanos = per_try_timeout.value.nanos
seconds = per_try_timeout.value.seconds
}
}
}
}
dynamic "timeout" {
for_each = (
route_action.value.timeout == null
? []
: [route_action.value.timeout]
)
content {
nanos = timeout.value.nanos
seconds = timeout.value.seconds
}
}
dynamic "url_rewrite" {
for_each = (
route_action.value.url_rewrite == null
? []
: [route_action.value.url_rewrite]
)
content {
host_rewrite = url_rewrite.value.host
path_prefix_rewrite = url_rewrite.value.path_prefix
}
}
dynamic "weighted_backend_services" {
for_each = coalesce(
route_action.value.weighted_backend_services, {}
)
iterator = service
content {
backend_service = lookup(
local.backend_ids, service.key, service.key
)
weight = service.value.weight
dynamic "header_action" {
for_each = (
service.value.header_action == null
? []
: [service.value.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
}
}
}
}
dynamic "default_url_redirect" {
for_each = (
m.value.default_url_redirect == null
? []
: [m.value.default_url_redirect]
)
content {
host_redirect = default_url_redirect.value.host
https_redirect = default_url_redirect.value.https
path_redirect = default_url_redirect.value.path
prefix_redirect = default_url_redirect.value.prefix
redirect_response_code = default_url_redirect.value.response_code
strip_query = default_url_redirect.value.strip_query
}
}
dynamic "header_action" {
for_each = (
m.value.header_action == null
? []
: [m.value.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
dynamic "path_rule" {
for_each = toset(coalesce(m.value.path_rules, []))
content {
paths = path_rule.value.paths
service = path_rule.value.service == null ? null : lookup(
local.backend_ids,
path_rule.value.service,
path_rule.value.service
)
dynamic "route_action" {
for_each = (
path_rule.value.route_action == null
? []
: [path_rule.value.route_action]
)
content {
dynamic "cors_policy" {
for_each = (
route_action.value.cors_policy == null
? []
: [route_action.value.cors_policy]
)
content {
allow_credentials = cors_policy.value.allow_credentials
allow_headers = cors_policy.value.allow_headers
allow_methods = cors_policy.value.allow_methods
allow_origin_regexes = cors_policy.value.allow_origin_regexes
allow_origins = cors_policy.value.allow_origins
disabled = cors_policy.value.disabled
expose_headers = cors_policy.value.expose_headers
max_age = cors_policy.value.max_age
}
}
dynamic "fault_injection_policy" {
for_each = (
route_action.value.fault_injection_policy == null
? []
: [route_action.value.fault_injection_policy]
)
content {
dynamic "abort" {
for_each = (
fault_injection_policy.value.abort == null
? []
: [fault_injection_policy.value.abort]
)
content {
http_status = abort.value.status
percentage = abort.value.percentage
}
}
dynamic "delay" {
for_each = (
fault_injection_policy.value.delay == null
? []
: [fault_injection_policy.value.delay]
)
content {
percentage = delay.value.percentage
fixed_delay {
nanos = delay.value.fixed.nanos
seconds = delay.value.fixed.seconds
}
}
}
}
}
dynamic "request_mirror_policy" {
for_each = (
route_action.value.request_mirror_backend == null
? []
: [""]
)
content {
backend_service = lookup(
local.backend_ids,
route_action.value.request_mirror_backend,
route_action.value.request_mirror_backend
)
}
}
dynamic "retry_policy" {
for_each = (
route_action.value.retry_policy == null
? []
: [route_action.value.retry_policy]
)
content {
num_retries = retry_policy.value.num_retries
retry_conditions = retry_policy.value.retry_conditions
dynamic "per_try_timeout" {
for_each = (
retry_policy.value.per_try_timeout == null
? []
: [retry_policy.value.per_try_timeout]
)
content {
nanos = per_try_timeout.value.nanos
seconds = per_try_timeout.value.seconds
}
}
}
}
dynamic "timeout" {
for_each = (
route_action.value.timeout == null
? []
: [route_action.value.timeout]
)
content {
nanos = timeout.value.nanos
seconds = timeout.value.seconds
}
}
dynamic "url_rewrite" {
for_each = (
route_action.value.url_rewrite == null
? []
: [route_action.value.url_rewrite]
)
content {
host_rewrite = url_rewrite.value.host
path_prefix_rewrite = url_rewrite.value.path_prefix
}
}
dynamic "weighted_backend_services" {
for_each = coalesce(
route_action.value.weighted_backend_services, {}
)
iterator = service
content {
backend_service = lookup(
local.backend_ids, service.key, service.key
)
weight = service.value.weight
dynamic "header_action" {
for_each = (
service.value.header_action == null
? []
: [service.value.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
}
}
}
}
dynamic "url_redirect" {
for_each = (
path_rule.value.url_redirect == null
? []
: [path_rule.value.url_redirect]
)
content {
host_redirect = url_redirect.value.host
https_redirect = url_redirect.value.https
path_redirect = url_redirect.value.path
prefix_redirect = url_redirect.value.prefix
redirect_response_code = url_redirect.value.response_code
strip_query = url_redirect.value.strip_query
}
}
}
}
dynamic "route_rules" {
for_each = toset(coalesce(m.value.route_rules, []))
content {
priority = route_rules.value.priority
service = route_rules.value.service == null ? null : lookup(
local.backend_ids,
route_rules.value.service,
route_rules.value.service
)
dynamic "header_action" {
for_each = (
route_rules.value.header_action == null
? []
: [route_rules.value.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
dynamic "match_rules" {
for_each = toset(coalesce(route_rules.value.match_rules, []))
content {
ignore_case = match_rules.value.ignore_case
full_path_match = (
try(match_rules.value.path.type, null) == "full"
? match_rules.value.path.value
: null
)
prefix_match = (
try(match_rules.value.path.type, null) == "prefix"
? match_rules.value.path.value
: null
)
regex_match = (
try(match_rules.value.path.type, null) == "regex"
? match_rules.value.path.value
: null
)
dynamic "header_matches" {
for_each = toset(coalesce(match_rules.value.headers, []))
iterator = h
content {
header_name = h.value.name
exact_match = h.value.type == "exact" ? h.value.value : null
invert_match = h.value.invert_match
prefix_match = h.value.type == "prefix" ? h.value.value : null
present_match = h.value.type == "present" ? h.value.value : null
regex_match = h.value.type == "regex" ? h.value.value : null
suffix_match = h.value.type == "suffix" ? h.value.value : null
dynamic "range_match" {
for_each = (
h.value.type != "range" || h.value.range_value == null
? []
: [""]
)
content {
range_end = h.value.range_value.end
range_start = h.value.range_value.start
}
}
}
}
dynamic "metadata_filters" {
for_each = toset(coalesce(match_rules.value.metadata_filters, []))
iterator = m
content {
filter_match_criteria = (
m.value.match_all ? "MATCH_ALL" : "MATCH_ANY"
)
dynamic "filter_labels" {
for_each = m.value.labels
content {
name = filter_labels.key
value = filter_labels.value
}
}
}
}
dynamic "query_parameter_matches" {
for_each = toset(coalesce(match_rules.value.query_params, []))
iterator = q
content {
name = q.value.name
exact_match = (
q.value.type == "exact" ? q.value.value : null
)
present_match = (
q.value.type == "present" ? q.value.value : null
)
regex_match = (
q.value.type == "regex" ? q.value.value : null
)
}
}
}
}
dynamic "route_action" {
for_each = (
route_rules.value.route_action == null
? []
: [route_rules.value.route_action]
)
content {
dynamic "cors_policy" {
for_each = (
route_action.value.cors_policy == null
? []
: [route_action.value.cors_policy]
)
content {
allow_credentials = cors_policy.value.allow_credentials
allow_headers = cors_policy.value.allow_headers
allow_methods = cors_policy.value.allow_methods
allow_origin_regexes = cors_policy.value.allow_origin_regexes
allow_origins = cors_policy.value.allow_origins
disabled = cors_policy.value.disabled
expose_headers = cors_policy.value.expose_headers
max_age = cors_policy.value.max_age
}
}
dynamic "fault_injection_policy" {
for_each = (
route_action.value.fault_injection_policy == null
? []
: [route_action.value.fault_injection_policy]
)
content {
dynamic "abort" {
for_each = (
fault_injection_policy.value.abort == null
? []
: [fault_injection_policy.value.abort]
)
content {
http_status = abort.value.status
percentage = abort.value.percentage
}
}
dynamic "delay" {
for_each = (
fault_injection_policy.value.delay == null
? []
: [fault_injection_policy.value.delay]
)
content {
percentage = delay.value.percentage
fixed_delay {
nanos = delay.value.fixed.nanos
seconds = delay.value.fixed.seconds
}
}
}
}
}
dynamic "request_mirror_policy" {
for_each = (
route_action.value.request_mirror_backend == null
? []
: [""]
)
content {
backend_service = lookup(
local.backend_ids,
route_action.value.request_mirror_backend,
route_action.value.request_mirror_backend
)
}
}
dynamic "retry_policy" {
for_each = (
route_action.value.retry_policy == null
? []
: [route_action.value.retry_policy]
)
content {
num_retries = retry_policy.value.num_retries
retry_conditions = retry_policy.value.retry_conditions
dynamic "per_try_timeout" {
for_each = (
retry_policy.value.per_try_timeout == null
? []
: [retry_policy.value.per_try_timeout]
)
content {
nanos = per_try_timeout.value.nanos
seconds = per_try_timeout.value.seconds
}
}
}
}
dynamic "timeout" {
for_each = (
route_action.value.timeout == null
? []
: [route_action.value.timeout]
)
content {
nanos = timeout.value.nanos
seconds = timeout.value.seconds
}
}
dynamic "url_rewrite" {
for_each = (
route_action.value.url_rewrite == null
? []
: [route_action.value.url_rewrite]
)
content {
host_rewrite = url_rewrite.value.host
path_prefix_rewrite = url_rewrite.value.path_prefix
}
}
dynamic "weighted_backend_services" {
for_each = coalesce(
route_action.value.weighted_backend_services, {}
)
iterator = service
content {
backend_service = lookup(
local.backend_ids, service.key, service.key
)
weight = service.value.weight
dynamic "header_action" {
for_each = (
service.value.header_action == null
? []
: [service.value.header_action]
)
iterator = h
content {
request_headers_to_remove = h.value.request_remove
response_headers_to_remove = h.value.response_remove
dynamic "request_headers_to_add" {
for_each = coalesce(h.value.request_add, {})
content {
header_name = request_headers_to_add.key
header_value = request_headers_to_add.value.value
replace = request_headers_to_add.value.replace
}
}
dynamic "response_headers_to_add" {
for_each = coalesce(h.value.response_add, {})
content {
header_name = response_headers_to_add.key
header_value = response_headers_to_add.value.value
replace = response_headers_to_add.value.replace
}
}
}
}
}
}
}
}
dynamic "url_redirect" {
for_each = (
route_rules.value.url_redirect == null
? []
: [route_rules.value.url_redirect]
)
content {
host_redirect = url_redirect.value.host
https_redirect = url_redirect.value.https
path_redirect = url_redirect.value.path
prefix_redirect = url_redirect.value.prefix
redirect_response_code = url_redirect.value.response_code
strip_query = url_redirect.value.strip_query
}
}
}
}
}
}
dynamic "test" {
for_each = toset(coalesce(var.urlmap_config.test, []))
content {
host = test.value.host
path = test.value.path
service = test.value.service
description = test.value.description
}
}
}

View File

@@ -0,0 +1,150 @@
/**
* 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 Backend services variables.
variable "backend_service_configs" {
description = "Backend service level configuration."
type = map(object({
affinity_cookie_ttl_sec = optional(number)
compression_mode = optional(string)
connection_draining_timeout_sec = optional(number)
custom_request_headers = optional(list(string))
custom_response_headers = optional(list(string))
enable_cdn = optional(bool)
health_checks = optional(list(string), ["default"])
log_sample_rate = optional(number)
port_name = optional(string)
project_id = optional(string)
protocol = optional(string)
security_policy = optional(string)
session_affinity = optional(string)
timeout_sec = optional(number)
backends = list(object({
# group renamed to backend
backend = string
balancing_mode = optional(string, "UTILIZATION")
capacity_scaler = optional(number, 1)
description = optional(string, "Terraform managed.")
failover = optional(bool, false)
max_connections = optional(object({
per_endpoint = optional(number)
per_group = optional(number)
per_instance = optional(number)
}))
max_rate = optional(object({
per_endpoint = optional(number)
per_group = optional(number)
per_instance = optional(number)
}))
max_utilization = optional(number)
}))
cdn_policy = optional(object({
cache_mode = optional(string)
client_ttl = optional(number)
default_ttl = optional(number)
max_ttl = optional(number)
negative_caching = optional(bool)
serve_while_stale = optional(number)
signed_url_cache_max_age_sec = optional(number)
cache_key_policy = optional(object({
include_host = optional(bool)
include_named_cookies = optional(list(string))
include_protocol = optional(bool)
include_query_string = optional(bool)
query_string_blacklist = optional(list(string))
query_string_whitelist = optional(list(string))
}))
negative_caching_policy = optional(object({
code = optional(number)
ttl = optional(number)
}))
}))
circuit_breakers = optional(object({
max_connections = optional(number)
max_pending_requests = optional(number)
max_requests = optional(number)
max_requests_per_connection = optional(number)
max_retries = optional(number)
connect_timeout = optional(object({
seconds = number
nanos = optional(number)
}))
}))
consistent_hash = optional(object({
http_header_name = optional(string)
minimum_ring_size = optional(number)
http_cookie = optional(object({
name = optional(string)
path = optional(string)
ttl = optional(object({
seconds = number
nanos = optional(number)
}))
}))
}))
iap_config = optional(object({
oauth2_client_id = string
oauth2_client_secret = string
oauth2_client_secret_sha256 = optional(string)
}))
outlier_detection = optional(object({
consecutive_errors = optional(number)
consecutive_gateway_failure = optional(number)
enforcing_consecutive_errors = optional(number)
enforcing_consecutive_gateway_failure = optional(number)
enforcing_success_rate = optional(number)
max_ejection_percent = optional(number)
success_rate_minimum_hosts = optional(number)
success_rate_request_volume = optional(number)
success_rate_stdev_factor = optional(number)
base_ejection_time = optional(object({
seconds = number
nanos = optional(number)
}))
interval = optional(object({
seconds = number
nanos = optional(number)
}))
}))
security_settings = optional(object({
client_tls_policy = string
subject_alt_names = list(string)
}))
}))
default = {}
nullable = false
validation {
condition = contains(
[
"-", "ROUND_ROBIN", "LEAST_REQUEST", "RING_HASH",
"RANDOM", "ORIGINAL_DESTINATION", "MAGLEV"
],
try(var.backend_service_configs.locality_lb_policy, "-")
)
error_message = "Invalid locality lb policy value."
}
validation {
condition = contains(
[
"NONE", "CLIENT_IP", "CLIENT_IP_NO_DESTINATION",
"CLIENT_IP_PORT_PROTO", "CLIENT_IP_PROTO"
],
try(var.backend_service_configs.session_affinity, "NONE")
)
error_message = "Invalid session affinity value."
}
}

View File

@@ -0,0 +1,106 @@
/**
* 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 Health check variable.
variable "health_check_configs" {
description = "Optional auto-created health check configurations, use the output self-link to set it in the auto healing policy. Refer to examples for usage."
type = map(object({
check_interval_sec = optional(number)
description = optional(string, "Terraform managed.")
enable_logging = optional(bool, false)
healthy_threshold = optional(number)
project_id = optional(string)
timeout_sec = optional(number)
unhealthy_threshold = optional(number)
grpc = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
service_name = optional(string)
}))
http = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
http2 = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
https = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
tcp = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request = optional(string)
response = optional(string)
}))
ssl = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request = optional(string)
response = optional(string)
}))
}))
default = {
default = {
http = {
port_specification = "USE_SERVING_PORT"
}
}
}
validation {
condition = alltrue([
for k, v in var.health_check_configs : (
(try(v.grpc, null) == null ? 0 : 1) +
(try(v.http, null) == null ? 0 : 1) +
(try(v.tcp, null) == null ? 0 : 1) <= 1
)
])
error_message = "At most one health check type can be configured at a time."
}
validation {
condition = alltrue(flatten([
for k, v in var.health_check_configs : [
for kk, vv in v : contains([
"-", "USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT"
], coalesce(try(vv.port_specification, null), "-"))
]
]))
error_message = "Invalid 'port_specification' value. Supported values are 'USE_FIXED_PORT', 'USE_NAMED_PORT', 'USE_SERVING_PORT'."
}
}

View File

@@ -0,0 +1,372 @@
/**
* 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 URLmap variable.
variable "urlmap_config" {
description = "The URL map configuration."
type = object({
default_route_action = optional(object({
request_mirror_backend = optional(string)
cors_policy = optional(object({
allow_credentials = optional(bool)
allow_headers = optional(string)
allow_methods = optional(string)
allow_origin_regexes = list(string)
allow_origins = list(string)
disabled = optional(bool)
expose_headers = optional(string)
max_age = optional(string)
}))
fault_injection_policy = optional(object({
abort = optional(object({
percentage = number
status = number
}))
delay = optional(object({
fixed = object({
seconds = number
nanos = number
})
percentage = number
}))
}))
retry_policy = optional(object({
num_retries = number
retry_conditions = optional(list(string))
per_try_timeout = optional(object({
seconds = number
nanos = optional(number)
}))
}))
timeout = optional(object({
seconds = number
nanos = optional(number)
}))
url_rewrite = optional(object({
host = optional(string)
path_prefix = optional(string)
}))
weighted_backend_services = optional(map(object({
weight = number
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
})))
}))
default_service = optional(string)
default_url_redirect = optional(object({
host = optional(string)
https = optional(bool)
path = optional(string)
prefix = optional(string)
response_code = optional(string)
strip_query = optional(bool)
}))
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
host_rules = optional(list(object({
hosts = list(string)
path_matcher = string
description = optional(string)
})))
path_matchers = optional(map(object({
description = optional(string)
default_route_action = optional(object({
request_mirror_backend = optional(string)
cors_policy = optional(object({
allow_credentials = optional(bool)
allow_headers = optional(string)
allow_methods = optional(string)
allow_origin_regexes = list(string)
allow_origins = list(string)
disabled = optional(bool)
expose_headers = optional(string)
max_age = optional(string)
}))
fault_injection_policy = optional(object({
abort = optional(object({
percentage = number
status = number
}))
delay = optional(object({
fixed = object({
seconds = number
nanos = number
})
percentage = number
}))
}))
retry_policy = optional(object({
num_retries = number
retry_conditions = optional(list(string))
per_try_timeout = optional(object({
seconds = number
nanos = optional(number)
}))
}))
timeout = optional(object({
seconds = number
nanos = optional(number)
}))
url_rewrite = optional(object({
host = optional(string)
path_prefix = optional(string)
}))
weighted_backend_services = optional(map(object({
weight = number
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
})))
}))
default_service = optional(string)
default_url_redirect = optional(object({
host = optional(string)
https = optional(bool)
path = optional(string)
prefix = optional(string)
response_code = optional(string)
strip_query = optional(bool)
}))
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
path_rules = optional(list(object({
paths = list(string)
service = optional(string)
route_action = optional(object({
request_mirror_backend = optional(string)
cors_policy = optional(object({
allow_credentials = optional(bool)
allow_headers = optional(string)
allow_methods = optional(string)
allow_origin_regexes = list(string)
allow_origins = list(string)
disabled = optional(bool)
expose_headers = optional(string)
max_age = optional(string)
}))
fault_injection_policy = optional(object({
abort = optional(object({
percentage = number
status = number
}))
delay = optional(object({
fixed = object({
seconds = number
nanos = number
})
percentage = number
}))
}))
retry_policy = optional(object({
num_retries = number
retry_conditions = optional(list(string))
per_try_timeout = optional(object({
seconds = number
nanos = optional(number)
}))
}))
timeout = optional(object({
seconds = number
nanos = optional(number)
}))
url_rewrite = optional(object({
host = optional(string)
path_prefix = optional(string)
}))
weighted_backend_services = optional(map(object({
weight = number
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
})))
}))
url_redirect = optional(object({
host = optional(string)
https = optional(bool)
path = optional(string)
prefix = optional(string)
response_code = optional(string)
strip_query = optional(bool)
}))
})))
route_rules = optional(list(object({
priority = number
service = optional(string)
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
match_rules = optional(list(object({
ignore_case = optional(bool, false)
headers = optional(list(object({
name = string
invert_match = optional(bool, false)
type = optional(string, "present") # exact, prefix, suffix, regex, present, range
value = optional(string)
range_value = optional(object({
end = string
start = string
}))
})))
metadata_filters = optional(list(object({
labels = map(string)
match_all = bool # MATCH_ANY, MATCH_ALL
})))
path = optional(object({
value = string
type = optional(string, "prefix") # full, prefix, regex
}))
query_params = optional(list(object({
name = string
value = string
type = optional(string, "present") # exact, present, regex
})))
})))
route_action = optional(object({
request_mirror_backend = optional(string)
cors_policy = optional(object({
allow_credentials = optional(bool)
allow_headers = optional(string)
allow_methods = optional(string)
allow_origin_regexes = list(string)
allow_origins = list(string)
disabled = optional(bool)
expose_headers = optional(string)
max_age = optional(string)
}))
fault_injection_policy = optional(object({
abort = optional(object({
percentage = number
status = number
}))
delay = optional(object({
fixed = object({
seconds = number
nanos = number
})
percentage = number
}))
}))
retry_policy = optional(object({
num_retries = number
retry_conditions = optional(list(string))
per_try_timeout = optional(object({
seconds = number
nanos = optional(number)
}))
}))
timeout = optional(object({
seconds = number
nanos = optional(number)
}))
url_rewrite = optional(object({
host = optional(string)
path_prefix = optional(string)
}))
weighted_backend_services = optional(map(object({
weight = number
header_action = optional(object({
request_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
request_remove = optional(list(string))
response_add = optional(map(object({
value = string
replace = optional(bool, true)
})))
response_remove = optional(list(string))
}))
})))
}))
url_redirect = optional(object({
host = optional(string)
https = optional(bool)
path = optional(string)
prefix = optional(string)
response_code = optional(string)
strip_query = optional(bool)
}))
})))
})))
test = optional(list(object({
host = string
path = string
service = string
description = optional(string)
})))
})
default = {
default_service = "default"
}
}

View File

@@ -0,0 +1,232 @@
/**
* 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.
*/
variable "address" {
description = "Optional IP address used for the forwarding rule."
type = string
default = null
}
variable "backend_buckets_config" {
description = "Backend buckets configuration."
type = map(object({
bucket_name = string
compression_mode = optional(string)
custom_response_headers = optional(list(string))
description = optional(string)
edge_security_policy = optional(string)
enable_cdn = optional(bool)
cdn_policy = optional(object({
bypass_cache_on_request_headers = optional(list(string))
cache_mode = optional(string)
client_ttl = optional(number)
default_ttl = optional(number)
max_ttl = optional(number)
negative_caching = optional(bool)
request_coalescing = optional(bool)
serve_while_stale = optional(number)
signed_url_cache_max_age_sec = optional(number)
cache_key_policy = optional(object({
include_http_headers = optional(list(string))
query_string_whitelist = optional(list(string))
}))
negative_caching_policy = optional(object({
code = optional(number)
ttl = optional(number)
}))
}))
}))
default = {}
nullable = true
}
variable "description" {
description = "Optional description used for resources."
type = string
default = "Terraform managed."
}
variable "group_configs" {
description = "Optional unmanaged groups to create. Can be referenced in backends via key or outputs."
type = map(object({
zone = string
instances = optional(list(string), [])
named_ports = optional(map(number), {})
project_id = optional(string)
}))
default = {}
nullable = false
}
variable "https_proxy_config" {
description = "HTTPS proxy connfiguration."
type = object({
certificate_map = optional(string)
quic_override = optional(string)
ssl_policy = optional(string)
})
default = {}
nullable = false
}
variable "labels" {
description = "Labels set on resources."
type = map(string)
default = {}
}
variable "name" {
description = "Load balancer name."
type = string
}
variable "neg_configs" {
description = "Optional network endpoint groups to create. Can be referenced in backends via key or outputs."
type = map(object({
description = optional(string)
cloudfunction = optional(object({
region = string
target_function = optional(string)
target_urlmask = optional(string)
}))
cloudrun = optional(object({
region = string
target_service = optional(object({
name = string
tag = optional(string)
}))
target_urlmask = optional(string)
}))
gce = optional(object({
network = string
subnetwork = string
zone = string
# default_port = optional(number)
endpoints = optional(map(object({
instance = string
ip_address = string
port = number
})))
}))
hybrid = optional(object({
network = string
zone = string
# re-enable once provider properly support this
# default_port = optional(number)
endpoints = optional(map(object({
ip_address = string
port = number
})))
}))
internet = optional(object({
use_fqdn = optional(bool, true)
# re-enable once provider properly support this
# default_port = optional(number)
endpoints = optional(map(object({
destination = string
port = number
})))
}))
psc = optional(object({
region = string
target_service = string
network = optional(string)
subnetwork = optional(string)
}))
}))
default = {}
nullable = false
validation {
condition = alltrue([
for k, v in var.neg_configs : (
(try(v.cloudfunction, null) == null ? 0 : 1) +
(try(v.cloudrun, null) == null ? 0 : 1) +
(try(v.gce, null) == null ? 0 : 1) +
(try(v.hybrid, null) == null ? 0 : 1) +
(try(v.internet, null) == null ? 0 : 1) +
(try(v.psc, null) == null ? 0 : 1) == 1
)
])
error_message = "Only one type of NEG can be configured at a time."
}
validation {
condition = alltrue([
for k, v in var.neg_configs : (
v.cloudrun == null
? true
: v.cloudrun.target_urlmask != null || v.cloudrun.target_service != null
)
])
error_message = "Cloud Run NEGs need either target service or target urlmask defined."
}
validation {
condition = alltrue([
for k, v in var.neg_configs : (
v.cloudfunction == null
? true
: v.cloudfunction.target_urlmask != null || v.cloudfunction.target_function != null
)
])
error_message = "Cloud Function NEGs need either target function or target urlmask defined."
}
}
variable "ports" {
description = "Optional ports for HTTP load balancer, valid ports are 80 and 8080."
type = list(string)
default = null
}
variable "project_id" {
description = "Project id."
type = string
}
variable "protocol" {
description = "Protocol supported by this load balancer."
type = string
default = "HTTP"
nullable = false
validation {
condition = (
var.protocol == null || var.protocol == "HTTP" || var.protocol == "HTTPS"
)
error_message = "Protocol must be HTTP or HTTPS"
}
}
variable "ssl_certificates" {
description = "SSL target proxy certificates (only if protocol is HTTPS) for existing, custom, and managed certificates."
type = object({
certificate_ids = optional(list(string), [])
create_configs = optional(map(object({
certificate = string
private_key = string
})), {})
managed_configs = optional(map(object({
domains = list(string)
description = optional(string)
})), {})
})
default = {}
nullable = false
}
variable "use_classic_version" {
description = "Use classic Global Load Balancer."
type = bool
default = true
}

View File

@@ -0,0 +1,29 @@
# 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
#
# https://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.
terraform {
required_version = ">= 1.4.4"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.69.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.69.0" # tftest
}
}
}