Refactor ILB module for Terraform 1.3 (#941)
* wip * wip * wip * backport health check to compute-mig * align blueprints and fast * fix blueprints * tfdoc
This commit is contained in:
parent
a214368800
commit
0563260678
|
@ -13,25 +13,54 @@
|
|||
# limitations under the License.
|
||||
|
||||
locals {
|
||||
prefix = var.prefix != "" ? format("%s-", var.prefix) : ""
|
||||
vpc_project = var.shared_vpc_project_id != null ? var.shared_vpc_project_id : module.project.project_id
|
||||
|
||||
ad_user_password_secret = "${local.cluster_full_name}-password"
|
||||
cluster_full_name = "${local.prefix}${var.cluster_name}"
|
||||
cluster_netbios_name = (
|
||||
length(local.cluster_full_name) > 15
|
||||
? substr(local.cluster_full_name, 0, 15)
|
||||
: local.cluster_full_name
|
||||
)
|
||||
network = module.vpc.self_link
|
||||
subnetwork = var.project_create != null ? module.vpc.subnet_self_links[format("%s/%s", var.region, var.subnetwork)] : data.google_compute_subnetwork.subnetwork[0].self_link
|
||||
|
||||
node_base = format("%s%s", local.prefix, var.node_name)
|
||||
node_prefix = length(local.node_base) > 12 ? substr(local.node_base, 0, 12) : local.node_base
|
||||
node_netbios_names = [for idx in range(1, 3) : format("%s-%02d", local.node_prefix, idx)]
|
||||
witness_name = format("%s%s", local.prefix, var.witness_name)
|
||||
witness_netbios_name = length(local.witness_name) > 15 ? substr(local.witness_name, 0, 15) : local.witness_name
|
||||
zones = var.project_create == null ? data.google_compute_zones.zones[0].names : formatlist("${var.region}-%s", ["a", "b", "c"])
|
||||
node_zones = merge({ for idx, node_name in local.node_netbios_names : node_name => local.zones[idx] },
|
||||
{ (local.witness_netbios_name) = local.zones[length(local.zones) - 1] })
|
||||
|
||||
cluster_full_name = format("%s%s", local.prefix, var.cluster_name)
|
||||
cluster_netbios_name = length(local.cluster_full_name) > 15 ? substr(local.cluster_full_name, 0, 15) : local.cluster_full_name
|
||||
|
||||
ad_user_password_secret = format("%s%s-password", local.prefix, var.cluster_name)
|
||||
node_base = "${local.prefix}${var.node_name}"
|
||||
node_prefix = (
|
||||
length(local.node_base) > 12
|
||||
? substr(local.node_base, 0, 12)
|
||||
: local.node_base
|
||||
)
|
||||
node_netbios_names = [
|
||||
for idx in range(1, 3) : format("%s-%02d", local.node_prefix, idx)
|
||||
]
|
||||
node_zones = merge(
|
||||
{
|
||||
for idx, node_name in local.node_netbios_names :
|
||||
node_name => local.zones[idx]
|
||||
},
|
||||
{
|
||||
(local.witness_netbios_name) = local.zones[length(local.zones) - 1]
|
||||
}
|
||||
)
|
||||
prefix = var.prefix != "" ? "${var.prefix}-" : ""
|
||||
subnetwork = (
|
||||
var.project_create != null
|
||||
? module.vpc.subnet_self_links["${var.region}/${var.subnetwork}"]
|
||||
: data.google_compute_subnetwork.subnetwork[0].self_link
|
||||
)
|
||||
vpc_project = (
|
||||
var.shared_vpc_project_id != null
|
||||
? var.shared_vpc_project_id
|
||||
: module.project.project_id
|
||||
)
|
||||
witness_name = "${local.prefix}${var.witness_name}"
|
||||
witness_netbios_name = (
|
||||
length(local.witness_name) > 15
|
||||
? substr(local.witness_name, 0, 15)
|
||||
: local.witness_name
|
||||
)
|
||||
zones = (
|
||||
var.project_create == null
|
||||
? data.google_compute_zones.zones[0].names
|
||||
: formatlist("${var.region}-%s", ["a", "b", "c"])
|
||||
)
|
||||
}
|
||||
|
||||
module "project" {
|
||||
|
|
|
@ -15,18 +15,11 @@
|
|||
# tfdoc:file:description Creates the VPC and manages the firewall rules and ILB.
|
||||
|
||||
locals {
|
||||
listeners = { for aog in var.always_on_groups : format("%slb-%s", local.prefix, aog) => {
|
||||
region = var.region
|
||||
subnetwork = local.subnetwork
|
||||
}
|
||||
}
|
||||
node_ips = { for node_name in local.node_netbios_names : node_name => {
|
||||
region = var.region
|
||||
subnetwork = local.subnetwork
|
||||
}
|
||||
}
|
||||
internal_addresses = merge({
|
||||
format("%scluster", local.prefix) = {
|
||||
internal_addresses = merge(
|
||||
local.listeners,
|
||||
local.node_ips,
|
||||
{
|
||||
"${local.prefix}cluster" = {
|
||||
region = var.region
|
||||
subnetwork = local.subnetwork
|
||||
}
|
||||
|
@ -34,7 +27,24 @@ locals {
|
|||
region = var.region
|
||||
subnetwork = local.subnetwork
|
||||
}
|
||||
}, local.listeners, local.node_ips)
|
||||
}
|
||||
)
|
||||
internal_address_ips = {
|
||||
for k, v in module.ip-addresses.internal_addresses :
|
||||
k => v.address
|
||||
}
|
||||
listeners = {
|
||||
for aog in var.always_on_groups : "${local.prefix}lb-${aog}" => {
|
||||
region = var.region
|
||||
subnetwork = local.subnetwork
|
||||
}
|
||||
}
|
||||
node_ips = {
|
||||
for node_name in local.node_netbios_names : node_name => {
|
||||
region = var.region
|
||||
subnetwork = local.subnetwork
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "google_compute_zones" "zones" {
|
||||
|
@ -50,7 +60,6 @@ data "google_compute_subnetwork" "subnetwork" {
|
|||
region = var.region
|
||||
}
|
||||
|
||||
# Create VPC if required
|
||||
module "vpc" {
|
||||
source = "../../../modules/net-vpc"
|
||||
|
||||
|
@ -66,7 +75,6 @@ module "vpc" {
|
|||
vpc_create = var.project_create != null ? true : false
|
||||
}
|
||||
|
||||
# Firewall rules required for WSFC nodes
|
||||
module "firewall" {
|
||||
source = "../../../modules/net-vpc-firewall"
|
||||
project_id = local.vpc_project
|
||||
|
@ -76,7 +84,7 @@ module "firewall" {
|
|||
https_source_ranges = []
|
||||
ssh_source_ranges = []
|
||||
custom_rules = {
|
||||
format("%sallow-all-between-wsfc-nodes", local.prefix) = {
|
||||
"${local.prefix}allow-all-between-wsfc-nodes" = {
|
||||
description = "Allow all between WSFC nodes"
|
||||
direction = "INGRESS"
|
||||
action = "allow"
|
||||
|
@ -91,7 +99,7 @@ module "firewall" {
|
|||
]
|
||||
extra_attributes = {}
|
||||
}
|
||||
format("%sallow-all-between-wsfc-witness", local.prefix) = {
|
||||
"${local.prefix}allow-all-between-wsfc-witness" = {
|
||||
description = "Allow all between WSFC witness nodes"
|
||||
direction = "INGRESS"
|
||||
action = "allow"
|
||||
|
@ -106,7 +114,7 @@ module "firewall" {
|
|||
]
|
||||
extra_attributes = {}
|
||||
}
|
||||
format("%sallow-sql-to-wsfc-nodes", local.prefix) = {
|
||||
"${local.prefix}allow-sql-to-wsfc-nodes" = {
|
||||
description = "Allow SQL connections to WSFC nodes"
|
||||
direction = "INGRESS"
|
||||
action = "allow"
|
||||
|
@ -119,7 +127,7 @@ module "firewall" {
|
|||
]
|
||||
extra_attributes = {}
|
||||
}
|
||||
format("%sallow-health-check-to-wsfc-nodes", local.prefix) = {
|
||||
"${local.prefix}allow-health-check-to-wsfc-nodes" = {
|
||||
description = "Allow health checks to WSFC nodes"
|
||||
direction = "INGRESS"
|
||||
action = "allow"
|
||||
|
@ -135,39 +143,31 @@ module "firewall" {
|
|||
}
|
||||
}
|
||||
|
||||
# IP Address reservation for cluster and listener
|
||||
module "ip-addresses" {
|
||||
source = "../../../modules/net-address"
|
||||
project_id = local.vpc_project
|
||||
|
||||
internal_addresses = local.internal_addresses
|
||||
}
|
||||
|
||||
# L4 Internal Load Balancer for SQL Listener
|
||||
module "listener-ilb" {
|
||||
source = "../../../modules/net-ilb"
|
||||
for_each = toset(var.always_on_groups)
|
||||
|
||||
project_id = var.project_id
|
||||
region = var.region
|
||||
|
||||
name = format("%s-%s-ilb", var.prefix, each.value)
|
||||
service_label = format("%s-%s-ilb", var.prefix, each.value)
|
||||
|
||||
address = module.ip-addresses.internal_addresses[format("%slb-%s", local.prefix, each.value)].address
|
||||
name = "${var.prefix}-${each.value}-ilb"
|
||||
service_label = "${var.prefix}-${each.value}-ilb"
|
||||
address = local.internal_address_ips["${local.prefix}lb-${each.value}"]
|
||||
vpc_config = {
|
||||
network = local.network
|
||||
subnetwork = local.subnetwork
|
||||
|
||||
}
|
||||
backends = [for k, node in module.nodes : {
|
||||
failover = false
|
||||
group = node.group.self_link
|
||||
balancing_mode = "CONNECTION"
|
||||
}]
|
||||
|
||||
health_check_config = {
|
||||
type = "tcp",
|
||||
check = { port = var.health_check_port },
|
||||
config = var.health_check_config,
|
||||
logging = true
|
||||
enable_logging = true
|
||||
tcp = {
|
||||
port = var.health_check_port
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,20 +199,20 @@ module "squid-ilb" {
|
|||
project_id = module.project-host.project_id
|
||||
region = var.region
|
||||
name = "squid-ilb"
|
||||
ports = [3128]
|
||||
service_label = "squid-ilb"
|
||||
vpc_config = {
|
||||
network = module.vpc.self_link
|
||||
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
|
||||
ports = [3128]
|
||||
}
|
||||
backends = [{
|
||||
failover = false
|
||||
group = module.squid-mig.0.group_manager.instance_group
|
||||
balancing_mode = "CONNECTION"
|
||||
}]
|
||||
health_check_config = {
|
||||
type = "tcp"
|
||||
check = { port = 3128 }
|
||||
config = {}
|
||||
logging = true
|
||||
enable_logging = true
|
||||
tcp = {
|
||||
port = 3128
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,22 +62,22 @@ module "ilb-left" {
|
|||
project_id = module.project.project_id
|
||||
region = var.region
|
||||
name = "${local.prefix}ilb-left"
|
||||
vpc_config = {
|
||||
network = module.vpc-left.self_link
|
||||
subnetwork = values(module.vpc-left.subnet_self_links)[0]
|
||||
}
|
||||
address = local.addresses.ilb-left
|
||||
ports = null
|
||||
backend_config = {
|
||||
backend_service_config = {
|
||||
session_affinity = var.ilb_session_affinity
|
||||
timeout_sec = null
|
||||
connection_draining_timeout_sec = null
|
||||
}
|
||||
backends = [for z, mod in module.gw : {
|
||||
failover = false
|
||||
group = mod.group.self_link
|
||||
balancing_mode = "CONNECTION"
|
||||
}]
|
||||
health_check_config = {
|
||||
type = "tcp", check = { port = 22 }, config = {}, logging = true
|
||||
enable_logging = true
|
||||
tcp = {
|
||||
port = 22
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,21 +86,21 @@ module "ilb-right" {
|
|||
project_id = module.project.project_id
|
||||
region = var.region
|
||||
name = "${local.prefix}ilb-right"
|
||||
vpc_config = {
|
||||
network = module.vpc-right.self_link
|
||||
subnetwork = values(module.vpc-right.subnet_self_links)[0]
|
||||
}
|
||||
address = local.addresses.ilb-right
|
||||
ports = null
|
||||
backend_config = {
|
||||
backend_service_config = {
|
||||
session_affinity = var.ilb_session_affinity
|
||||
timeout_sec = null
|
||||
connection_draining_timeout_sec = null
|
||||
}
|
||||
backends = [for z, mod in module.gw : {
|
||||
failover = false
|
||||
group = mod.group.self_link
|
||||
balancing_mode = "CONNECTION"
|
||||
}]
|
||||
health_check_config = {
|
||||
type = "tcp", check = { port = 22 }, config = {}, logging = true
|
||||
enable_logging = true
|
||||
tcp = {
|
||||
port = 22
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,16 +120,20 @@ module "ilb-nva-untrusted" {
|
|||
name = "nva-untrusted-${each.value.0}"
|
||||
service_label = var.prefix
|
||||
global_access = true
|
||||
vpc_config = {
|
||||
network = module.landing-untrusted-vpc.self_link
|
||||
subnetwork = module.landing-untrusted-vpc.subnet_self_links["${each.key}/landing-untrusted-default-${each.value.0}"]
|
||||
backends = [for key, _ in local.nva_locality :
|
||||
{
|
||||
failover = false
|
||||
}
|
||||
backends = [
|
||||
for key, _ in local.nva_locality : {
|
||||
group = module.nva-mig[key].group_manager.instance_group
|
||||
balancing_mode = "CONNECTION"
|
||||
} if local.nva_locality[key].region == each.key]
|
||||
} if local.nva_locality[key].region == each.key
|
||||
]
|
||||
health_check_config = {
|
||||
type = "tcp", check = { port = 22 }, config = {}, logging = false
|
||||
enable_logging = true
|
||||
tcp = {
|
||||
port = 22
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,16 +146,20 @@ module "ilb-nva-trusted" {
|
|||
name = "nva-trusted-${each.value.0}"
|
||||
service_label = var.prefix
|
||||
global_access = true
|
||||
vpc_config = {
|
||||
network = module.landing-trusted-vpc.self_link
|
||||
subnetwork = module.landing-trusted-vpc.subnet_self_links["${each.key}/landing-trusted-default-${each.value.0}"]
|
||||
backends = [for key, _ in local.nva_locality :
|
||||
{
|
||||
failover = false
|
||||
}
|
||||
backends = [
|
||||
for key, _ in local.nva_locality : {
|
||||
group = module.nva-mig[key].group_manager.instance_group
|
||||
balancing_mode = "CONNECTION"
|
||||
} if local.nva_locality[key].region == each.key]
|
||||
} if local.nva_locality[key].region == each.key
|
||||
]
|
||||
health_check_config = {
|
||||
type = "tcp", check = { port = 22 }, config = {}, logging = false
|
||||
enable_logging = true
|
||||
tcp = {
|
||||
port = 22
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -417,25 +417,25 @@ module "nginx-mig" {
|
|||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [instance_template](variables.tf#L150) | Instance template for the default version. | <code>string</code> | ✓ | |
|
||||
| [location](variables.tf#L155) | Compute zone or region. | <code>string</code> | ✓ | |
|
||||
| [name](variables.tf#L160) | Managed group name. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L171) | Project id. | <code>string</code> | ✓ | |
|
||||
| [instance_template](variables.tf#L174) | Instance template for the default version. | <code>string</code> | ✓ | |
|
||||
| [location](variables.tf#L179) | Compute zone or region. | <code>string</code> | ✓ | |
|
||||
| [name](variables.tf#L184) | Managed group name. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L195) | Project id. | <code>string</code> | ✓ | |
|
||||
| [all_instances_config](variables.tf#L17) | Metadata and labels set to all instances in the group. | <code title="object({ labels = optional(map(string)) metadata = optional(map(string)) })">object({…})</code> | | <code>null</code> |
|
||||
| [auto_healing_policies](variables.tf#L26) | Auto-healing policies for this group. | <code title="object({ health_check = optional(string) initial_delay_sec = number })">object({…})</code> | | <code>null</code> |
|
||||
| [autoscaler_config](variables.tf#L35) | Optional autoscaler configuration. | <code title="object({ max_replicas = number min_replicas = number cooldown_period = optional(number) mode = optional(string) # OFF, ONLY_UP, ON scaling_control = optional(object({ down = optional(object({ max_replicas_fixed = optional(number) max_replicas_percent = optional(number) time_window_sec = optional(number) })) in = optional(object({ max_replicas_fixed = optional(number) max_replicas_percent = optional(number) time_window_sec = optional(number) })) }), {}) scaling_signals = optional(object({ cpu_utilization = optional(object({ target = number optimize_availability = optional(bool) })) load_balancing_utilization = optional(object({ target = number })) metrics = optional(list(object({ name = string type = string # GAUGE, DELTA_PER_SECOND, DELTA_PER_MINUTE target_value = number single_instance_assignment = optional(number) time_series_filter = optional(string) }))) schedules = optional(list(object({ duration_sec = number name = string min_required_replicas = number cron_schedule = string description = optional(bool) timezone = optional(string) disabled = optional(bool) }))) }), {}) })">object({…})</code> | | <code>null</code> |
|
||||
| [default_version_name](variables.tf#L83) | Name used for the default version. | <code>string</code> | | <code>"default"</code> |
|
||||
| [description](variables.tf#L89) | Optional description used for all resources managed by this module. | <code>string</code> | | <code>"Terraform managed."</code> |
|
||||
| [distribution_policy](variables.tf#L95) | DIstribution policy for regional MIG. | <code title="object({ target_shape = optional(string) zones = optional(list(string)) })">object({…})</code> | | <code>null</code> |
|
||||
| [health_check_config](variables.tf#L104) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code title="object({ check_interval_sec = optional(number) description = optional(string, "Terraform managed.") enable_logging = optional(bool, false) healthy_threshold = optional(number) 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) use_protocol = optional(string, "http") # http http2 https })) 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) use_ssl = optional(bool, false) })) })">object({…})</code> | | <code>null</code> |
|
||||
| [named_ports](variables.tf#L165) | Named ports. | <code>map(number)</code> | | <code>null</code> |
|
||||
| [stateful_config](variables.tf#L183) | Stateful configuration for individual instances. | <code title="map(object({ minimal_action = optional(string) most_disruptive_action = optional(string) remove_state_on_destroy = optional(bool) preserved_state = optional(object({ disks = optional(map(object({ source = string delete_on_instance_deletion = optional(bool) read_only = optional(bool) }))) metadata = optional(map(string)) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [stateful_disks](variables.tf#L176) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | <code>map(bool)</code> | | <code>{}</code> |
|
||||
| [target_pools](variables.tf#L202) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [target_size](variables.tf#L208) | Group target size, leave null when using an autoscaler. | <code>number</code> | | <code>null</code> |
|
||||
| [update_policy](variables.tf#L214) | Update policy. Minimal action and type are required. | <code title="object({ minimal_action = string type = string max_surge = optional(object({ fixed = optional(number) percent = optional(number) })) max_unavailable = optional(object({ fixed = optional(number) percent = optional(number) })) min_ready_sec = optional(number) most_disruptive_action = optional(string) regional_redistribution_type = optional(string) replacement_method = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
| [versions](variables.tf#L235) | Additional application versions, target_size is optional. | <code title="map(object({ instance_template = string target_size = optional(object({ fixed = optional(number) percent = optional(number) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [wait_for_instances](variables.tf#L248) | Wait for all instances to be created/updated before returning. | <code title="object({ enabled = bool status = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
| [health_check_config](variables.tf#L104) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code title="object({ check_interval_sec = optional(number) description = optional(string, "Terraform managed.") enable_logging = optional(bool, false) healthy_threshold = optional(number) 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) })) })">object({…})</code> | | <code>null</code> |
|
||||
| [named_ports](variables.tf#L189) | Named ports. | <code>map(number)</code> | | <code>null</code> |
|
||||
| [stateful_config](variables.tf#L207) | Stateful configuration for individual instances. | <code title="map(object({ minimal_action = optional(string) most_disruptive_action = optional(string) remove_state_on_destroy = optional(bool) preserved_state = optional(object({ disks = optional(map(object({ source = string delete_on_instance_deletion = optional(bool) read_only = optional(bool) }))) metadata = optional(map(string)) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [stateful_disks](variables.tf#L200) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | <code>map(bool)</code> | | <code>{}</code> |
|
||||
| [target_pools](variables.tf#L226) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [target_size](variables.tf#L232) | Group target size, leave null when using an autoscaler. | <code>number</code> | | <code>null</code> |
|
||||
| [update_policy](variables.tf#L238) | Update policy. Minimal action and type are required. | <code title="object({ minimal_action = string type = string max_surge = optional(object({ fixed = optional(number) percent = optional(number) })) max_unavailable = optional(object({ fixed = optional(number) percent = optional(number) })) min_ready_sec = optional(number) most_disruptive_action = optional(string) regional_redistribution_type = optional(string) replacement_method = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
| [versions](variables.tf#L259) | Additional application versions, target_size is optional. | <code title="map(object({ instance_template = string target_size = optional(object({ fixed = optional(number) percent = optional(number) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [wait_for_instances](variables.tf#L272) | Wait for all instances to be created/updated before returning. | <code title="object({ enabled = bool status = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
|
|
@ -19,23 +19,14 @@
|
|||
locals {
|
||||
hc = var.health_check_config
|
||||
hc_grpc = try(local.hc.grpc, null) != null
|
||||
hc_http = (
|
||||
try(local.hc.http, null) != null &&
|
||||
lower(try(local.hc.http.use_protocol, "")) == "http"
|
||||
)
|
||||
hc_http2 = (
|
||||
try(local.hc.http, null) != null &&
|
||||
lower(try(local.hc.http.use_protocol, "")) == "http2"
|
||||
)
|
||||
hc_https = (
|
||||
try(local.hc.http, null) != null &&
|
||||
lower(try(local.hc.http.use_protocol, "")) == "https"
|
||||
)
|
||||
hc_ssl = try(local.hc.tcp.use_ssl, null) == true
|
||||
hc_tcp = try(local.hc.tcp, null) != null && !local.hc_ssl
|
||||
hc_http = try(local.hc.http, null) != null
|
||||
hc_http2 = try(local.hc.http2, null) != null
|
||||
hc_https = try(local.hc.https, null) != null
|
||||
hc_ssl = try(local.hc.ssl, null) != null
|
||||
hc_tcp = try(local.hc.tcp, null) != null
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "autohealing" {
|
||||
resource "google_compute_health_check" "default" {
|
||||
provider = google-beta
|
||||
count = local.hc != null ? 1 : 0
|
||||
project = var.project_id
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
locals {
|
||||
health_check = (
|
||||
try(var.auto_healing_policies.health_check, null) == null
|
||||
? try(google_compute_health_check.autohealing.0.self_link, null)
|
||||
? try(google_compute_health_check.default.0.self_link, null)
|
||||
: try(var.auto_healing_policies.health_check, null)
|
||||
)
|
||||
instance_group_manager = (
|
||||
|
|
|
@ -37,6 +37,6 @@ output "health_check" {
|
|||
value = (
|
||||
var.health_check_config == null
|
||||
? null
|
||||
: google_compute_health_check.autohealing.0
|
||||
: google_compute_health_check.default.0
|
||||
)
|
||||
}
|
||||
|
|
|
@ -124,7 +124,24 @@ variable "health_check_config" {
|
|||
proxy_header = optional(string)
|
||||
request_path = optional(string)
|
||||
response = optional(string)
|
||||
use_protocol = optional(string, "http") # http http2 https
|
||||
}))
|
||||
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)
|
||||
|
@ -133,7 +150,14 @@ variable "health_check_config" {
|
|||
proxy_header = optional(string)
|
||||
request = optional(string)
|
||||
response = optional(string)
|
||||
use_ssl = optional(bool, false)
|
||||
}))
|
||||
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 = null
|
||||
|
|
|
@ -23,11 +23,13 @@ module "ilb" {
|
|||
region = "europe-west1"
|
||||
name = "ilb-test"
|
||||
service_label = "ilb-test"
|
||||
vpc_config = {
|
||||
network = var.vpc.self_link
|
||||
subnetwork = var.subnet.self_link
|
||||
}
|
||||
group_configs = {
|
||||
my-group = {
|
||||
zone = "europe-west1-b", named_ports = null
|
||||
zone = "europe-west1-b"
|
||||
instances = [
|
||||
"instance-1-self-link",
|
||||
"instance-2-self-link"
|
||||
|
@ -35,12 +37,12 @@ module "ilb" {
|
|||
}
|
||||
}
|
||||
backends = [{
|
||||
failover = false
|
||||
group = module.ilb.groups.my-group.self_link
|
||||
balancing_mode = "CONNECTION"
|
||||
}]
|
||||
health_check_config = {
|
||||
type = "http", check = { port = 80 }, config = {}, logging = true
|
||||
http = {
|
||||
port = 80
|
||||
}
|
||||
}
|
||||
}
|
||||
# tftest modules=1 resources=4
|
||||
|
@ -91,18 +93,21 @@ module "ilb" {
|
|||
region = "europe-west1"
|
||||
name = "ilb-test"
|
||||
service_label = "ilb-test"
|
||||
vpc_config = {
|
||||
network = var.vpc.self_link
|
||||
subnetwork = var.subnet.self_link
|
||||
}
|
||||
ports = [80]
|
||||
backends = [
|
||||
for z, mod in module.instance-group : {
|
||||
failover = false
|
||||
group = mod.group.self_link
|
||||
balancing_mode = "CONNECTION"
|
||||
balancing_mode = "UTILIZATION"
|
||||
}
|
||||
]
|
||||
health_check_config = {
|
||||
type = "http", check = { port = 80 }, config = {}, logging = true
|
||||
http = {
|
||||
port = 80
|
||||
}
|
||||
}
|
||||
}
|
||||
# tftest modules=3 resources=7
|
||||
|
@ -113,37 +118,36 @@ module "ilb" {
|
|||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [backends](variables.tf#L33) | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | <code title="list(object({ failover = bool group = string balancing_mode = string }))">list(object({…}))</code> | ✓ | |
|
||||
| [name](variables.tf#L98) | Name used for all resources. | <code>string</code> | ✓ | |
|
||||
| [network](variables.tf#L103) | Network used for resources. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L114) | Project id where resources will be created. | <code>string</code> | ✓ | |
|
||||
| [region](variables.tf#L125) | GCP region. | <code>string</code> | ✓ | |
|
||||
| [subnetwork](variables.tf#L136) | Subnetwork used for the forwarding rule. | <code>string</code> | ✓ | |
|
||||
| [name](variables.tf#L184) | Name used for all resources. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L195) | Project id where resources will be created. | <code>string</code> | ✓ | |
|
||||
| [region](variables.tf#L206) | GCP region. | <code>string</code> | ✓ | |
|
||||
| [vpc_config](variables.tf#L217) | VPC-level configuration. | <code title="object({ network = string subnetwork = string })">object({…})</code> | ✓ | |
|
||||
| [address](variables.tf#L17) | Optional IP address used for the forwarding rule. | <code>string</code> | | <code>null</code> |
|
||||
| [backend_config](variables.tf#L23) | Optional backend configuration. | <code title="object({ session_affinity = string timeout_sec = number connection_draining_timeout_sec = number })">object({…})</code> | | <code>null</code> |
|
||||
| [failover_config](variables.tf#L42) | Optional failover configuration. | <code title="object({ disable_connection_drain = bool drop_traffic_if_unhealthy = bool ratio = number })">object({…})</code> | | <code>null</code> |
|
||||
| [global_access](variables.tf#L52) | Global access, defaults to false if not set. | <code>bool</code> | | <code>null</code> |
|
||||
| [group_configs](variables.tf#L58) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code title="map(object({ instances = list(string) named_ports = map(number) zone = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [health_check](variables.tf#L68) | Name of existing health check to use, disables auto-created health check. | <code>string</code> | | <code>null</code> |
|
||||
| [health_check_config](variables.tf#L74) | Configuration of the auto-created helth check. | <code title="object({ type = string # http https tcp ssl http2 check = map(any) # actual health check block attributes config = map(number) # interval, thresholds, timeout logging = bool })">object({…})</code> | | <code title="{ type = "http" check = { port_specification = "USE_SERVING_PORT" } config = {} logging = false }">{…}</code> |
|
||||
| [labels](variables.tf#L92) | Labels set on resources. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [ports](variables.tf#L108) | Comma-separated ports, leave null to use all ports. | <code>list(string)</code> | | <code>null</code> |
|
||||
| [protocol](variables.tf#L119) | IP protocol used, defaults to TCP. | <code>string</code> | | <code>"TCP"</code> |
|
||||
| [service_label](variables.tf#L130) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
|
||||
| [backend_service_config](variables.tf#L23) | Backend service level configuration. | <code title="object({ connection_draining_timeout_sec = optional(number) connection_tracking = optional(object({ idle_timeout_sec = optional(number) persist_conn_on_unhealthy = optional(string) track_per_session = optional(bool) })) enable_subsetting = optional(bool) failover_config = optional(object({ disable_conn_drain = optional(bool) drop_traffic_if_unhealthy = optional(bool) ratio = optional(number) })) log_sample_rate = optional(number) session_affinity = optional(string) timeout_sec = optional(number) })">object({…})</code> | | <code>{}</code> |
|
||||
| [backends](variables.tf#L56) | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | <code title="list(object({ group = string balancing_mode = optional(string, "CONNECTION") description = optional(string, "Terraform managed.") failover = optional(bool, false) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||
| [description](variables.tf#L75) | Optional description used for resources. | <code>string</code> | | <code>"Terraform managed."</code> |
|
||||
| [global_access](variables.tf#L81) | Global access, defaults to false if not set. | <code>bool</code> | | <code>null</code> |
|
||||
| [group_configs](variables.tf#L87) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code title="map(object({ zone = string instances = optional(list(string), []) named_ports = optional(map(number), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [health_check](variables.tf#L98) | Name of existing health check to use, disables auto-created health check. | <code>string</code> | | <code>null</code> |
|
||||
| [health_check_config](variables.tf#L104) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code title="object({ check_interval_sec = optional(number) description = optional(string, "Terraform managed.") enable_logging = optional(bool, false) healthy_threshold = optional(number) 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) })) })">object({…})</code> | | <code title="{ tcp = { port_specification = "USE_SERVING_PORT" } }">{…}</code> |
|
||||
| [labels](variables.tf#L178) | Labels set on resources. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [ports](variables.tf#L189) | Comma-separated ports, leave null to use all ports. | <code>list(string)</code> | | <code>null</code> |
|
||||
| [protocol](variables.tf#L200) | IP protocol used, defaults to TCP. | <code>string</code> | | <code>"TCP"</code> |
|
||||
| [service_label](variables.tf#L211) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [backend](outputs.tf#L17) | Backend resource. | |
|
||||
| [backend_id](outputs.tf#L22) | Backend id. | |
|
||||
| [backend_self_link](outputs.tf#L27) | Backend self link. | |
|
||||
| [backend_service](outputs.tf#L17) | Backend resource. | |
|
||||
| [backend_service_id](outputs.tf#L22) | Backend id. | |
|
||||
| [backend_service_self_link](outputs.tf#L27) | Backend self link. | |
|
||||
| [forwarding_rule](outputs.tf#L32) | Forwarding rule resource. | |
|
||||
| [forwarding_rule_address](outputs.tf#L37) | Forwarding rule address. | |
|
||||
| [forwarding_rule_id](outputs.tf#L42) | Forwarding rule id. | |
|
||||
| [forwarding_rule_self_link](outputs.tf#L47) | Forwarding rule self link. | |
|
||||
| [group_self_links](outputs.tf#L52) | Optional unmanaged instance group self links. | |
|
||||
| [groups](outputs.tf#L59) | Optional unmanaged instance group resources. | |
|
||||
| [group_self_links](outputs.tf#L57) | Optional unmanaged instance group self links. | |
|
||||
| [groups](outputs.tf#L52) | Optional unmanaged instance group resources. | |
|
||||
| [health_check](outputs.tf#L64) | Auto-created health-check resource. | |
|
||||
| [health_check_self_id](outputs.tf#L69) | Auto-created health-check self id. | |
|
||||
| [health_check_self_link](outputs.tf#L74) | Auto-created health-check self link. | |
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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 Optional instance group resources.
|
||||
|
||||
resource "google_compute_instance_group" "unmanaged" {
|
||||
for_each = var.group_configs
|
||||
project = var.project_id
|
||||
zone = each.value.zone
|
||||
name = each.key
|
||||
description = "Terraform-managed."
|
||||
instances = each.value.instances
|
||||
dynamic "named_port" {
|
||||
for_each = each.value.named_ports
|
||||
content {
|
||||
name = named_port.key
|
||||
port = named_port.value
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* 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.
|
||||
|
||||
locals {
|
||||
hc = var.health_check_config
|
||||
hc_grpc = try(local.hc.grpc, null) != null
|
||||
hc_http = try(local.hc.http, null) != null
|
||||
hc_http2 = try(local.hc.http2, null) != null
|
||||
hc_https = try(local.hc.https, null) != null
|
||||
hc_ssl = try(local.hc.ssl, null) != null
|
||||
hc_tcp = try(local.hc.tcp, null) != null
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "default" {
|
||||
provider = google-beta
|
||||
count = local.hc != null ? 1 : 0
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = local.hc.description
|
||||
check_interval_sec = local.hc.check_interval_sec
|
||||
healthy_threshold = local.hc.healthy_threshold
|
||||
timeout_sec = local.hc.timeout_sec
|
||||
unhealthy_threshold = local.hc.unhealthy_threshold
|
||||
|
||||
dynamic "grpc_health_check" {
|
||||
for_each = local.hc_grpc ? [""] : []
|
||||
content {
|
||||
port = local.hc.grpc.port
|
||||
port_name = local.hc.grpc.port_name
|
||||
port_specification = local.hc.grpc.port_specification
|
||||
grpc_service_name = local.hc.grpc.service_name
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "http_health_check" {
|
||||
for_each = local.hc_http ? [""] : []
|
||||
content {
|
||||
host = local.hc.http.host
|
||||
port = local.hc.http.port
|
||||
port_name = local.hc.http.port_name
|
||||
port_specification = local.hc.http.port_specification
|
||||
proxy_header = local.hc.http.proxy_header
|
||||
request_path = local.hc.http.request_path
|
||||
response = local.hc.http.response
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "http2_health_check" {
|
||||
for_each = local.hc_http2 ? [""] : []
|
||||
content {
|
||||
host = local.hc.http.host
|
||||
port = local.hc.http.port
|
||||
port_name = local.hc.http.port_name
|
||||
port_specification = local.hc.http.port_specification
|
||||
proxy_header = local.hc.http.proxy_header
|
||||
request_path = local.hc.http.request_path
|
||||
response = local.hc.http.response
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "https_health_check" {
|
||||
for_each = local.hc_https ? [""] : []
|
||||
content {
|
||||
host = local.hc.http.host
|
||||
port = local.hc.http.port
|
||||
port_name = local.hc.http.port_name
|
||||
port_specification = local.hc.http.port_specification
|
||||
proxy_header = local.hc.http.proxy_header
|
||||
request_path = local.hc.http.request_path
|
||||
response = local.hc.http.response
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "ssl_health_check" {
|
||||
for_each = local.hc_ssl ? [""] : []
|
||||
content {
|
||||
port = local.hc.tcp.port
|
||||
port_name = local.hc.tcp.port_name
|
||||
port_specification = local.hc.tcp.port_specification
|
||||
proxy_header = local.hc.tcp.proxy_header
|
||||
request = local.hc.tcp.request
|
||||
response = local.hc.tcp.response
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "tcp_health_check" {
|
||||
for_each = local.hc_tcp ? [""] : []
|
||||
content {
|
||||
port = local.hc.tcp.port
|
||||
port_name = local.hc.tcp.port_name
|
||||
port_specification = local.hc.tcp.port_specification
|
||||
proxy_header = local.hc.tcp.proxy_header
|
||||
request = local.hc.tcp.request
|
||||
response = local.hc.tcp.response
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = try(local.hc.enable_logging, null) == true ? [""] : []
|
||||
content {
|
||||
enable = true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,252 +16,100 @@
|
|||
|
||||
|
||||
locals {
|
||||
bs_conntrack = var.backend_service_config.connection_tracking
|
||||
bs_failover = var.backend_service_config.failover_config
|
||||
health_check = (
|
||||
var.health_check != null
|
||||
? var.health_check
|
||||
: try(local.health_check_resource.self_link, null)
|
||||
: google_compute_health_check.default.0.self_link
|
||||
)
|
||||
health_check_resource = try(
|
||||
google_compute_health_check.http.0,
|
||||
google_compute_health_check.https.0,
|
||||
google_compute_health_check.tcp.0,
|
||||
google_compute_health_check.ssl.0,
|
||||
google_compute_health_check.http2.0,
|
||||
{}
|
||||
)
|
||||
health_check_type = try(var.health_check_config.type, null)
|
||||
}
|
||||
|
||||
resource "google_compute_forwarding_rule" "default" {
|
||||
provider = google-beta
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
load_balancing_scheme = "INTERNAL"
|
||||
region = var.region
|
||||
network = var.network
|
||||
subnetwork = var.subnetwork
|
||||
name = var.name
|
||||
description = var.description
|
||||
ip_address = var.address
|
||||
ip_protocol = var.protocol # TCP | UDP
|
||||
backend_service = (
|
||||
google_compute_region_backend_service.default.self_link
|
||||
)
|
||||
load_balancing_scheme = "INTERNAL"
|
||||
network = var.vpc_config.network
|
||||
ports = var.ports # "nnnnn" or "nnnnn,nnnnn,nnnnn" max 5
|
||||
service_label = var.service_label
|
||||
all_ports = var.ports == null ? true : null
|
||||
subnetwork = var.vpc_config.subnetwork
|
||||
allow_global_access = var.global_access
|
||||
backend_service = google_compute_region_backend_service.default.self_link
|
||||
# is_mirroring_collector = false
|
||||
labels = var.labels
|
||||
all_ports = var.ports == null ? true : null
|
||||
service_label = var.service_label
|
||||
# is_mirroring_collector = false
|
||||
}
|
||||
|
||||
resource "google_compute_region_backend_service" "default" {
|
||||
provider = google-beta
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
load_balancing_scheme = "INTERNAL"
|
||||
region = var.region
|
||||
network = var.network
|
||||
health_checks = [local.health_check]
|
||||
name = var.name
|
||||
description = var.description
|
||||
load_balancing_scheme = "INTERNAL"
|
||||
protocol = var.protocol
|
||||
|
||||
session_affinity = try(var.backend_config.session_affinity, null)
|
||||
timeout_sec = try(var.backend_config.timeout_sec, null)
|
||||
connection_draining_timeout_sec = try(var.backend_config.connection_draining_timeout_sec, null)
|
||||
network = var.vpc_config.network
|
||||
health_checks = [local.health_check]
|
||||
connection_draining_timeout_sec = var.backend_service_config.connection_draining_timeout_sec
|
||||
session_affinity = var.backend_service_config.session_affinity
|
||||
timeout_sec = var.backend_service_config.timeout_sec
|
||||
|
||||
dynamic "backend" {
|
||||
for_each = { for b in var.backends : b.group => b }
|
||||
iterator = backend
|
||||
content {
|
||||
balancing_mode = backend.value.balancing_mode
|
||||
description = "Terraform managed."
|
||||
description = backend.value.description
|
||||
failover = backend.value.failover
|
||||
group = backend.key
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "connection_tracking_policy" {
|
||||
for_each = local.bs_conntrack == null ? [] : [""]
|
||||
content {
|
||||
connection_persistence_on_unhealthy_backends = (
|
||||
local.bs_conntrack.persist_conn_on_unhealthy != null
|
||||
? local.bs_conntrack.persist_conn_on_unhealthy
|
||||
: null
|
||||
)
|
||||
idle_timeout_sec = local.bs_conntrack.idle_timeout_sec
|
||||
tracking_mode = (
|
||||
local.bs_conntrack.track_per_session != null
|
||||
? local.bs_conntrack.track_per_session
|
||||
: null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "failover_policy" {
|
||||
for_each = var.failover_config == null ? [] : [var.failover_config]
|
||||
iterator = config
|
||||
for_each = local.bs_failover == null ? [] : [""]
|
||||
content {
|
||||
disable_connection_drain_on_failover = config.value.disable_connection_drain
|
||||
drop_traffic_if_unhealthy = config.value.drop_traffic_if_unhealthy
|
||||
failover_ratio = config.value.ratio
|
||||
disable_connection_drain_on_failover = local.bs_failover.disable_conn_drain
|
||||
drop_traffic_if_unhealthy = local.bs_failover.drop_traffic_if_unhealthy
|
||||
failover_ratio = local.bs_failover.ratio
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "google_compute_instance_group" "unmanaged" {
|
||||
for_each = var.group_configs
|
||||
project = var.project_id
|
||||
zone = each.value.zone
|
||||
name = each.key
|
||||
description = "Terraform-managed."
|
||||
instances = each.value.instances
|
||||
dynamic "named_port" {
|
||||
for_each = each.value.named_ports != null ? each.value.named_ports : {}
|
||||
iterator = config
|
||||
content {
|
||||
name = config.key
|
||||
port = config.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "http" {
|
||||
provider = google-beta
|
||||
count = (
|
||||
var.health_check == null && local.health_check_type == "http" ? 1 : 0
|
||||
)
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
|
||||
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
|
||||
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
|
||||
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
|
||||
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
|
||||
|
||||
http_health_check {
|
||||
host = try(var.health_check_config.check.host, null)
|
||||
port = try(var.health_check_config.check.port, null)
|
||||
port_name = try(var.health_check_config.check.port_name, null)
|
||||
port_specification = try(var.health_check_config.check.port_specification, null)
|
||||
proxy_header = try(var.health_check_config.check.proxy_header, null)
|
||||
request_path = try(var.health_check_config.check.request_path, null)
|
||||
response = try(var.health_check_config.check.response, null)
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = try(var.health_check_config.logging, false) ? [""] : []
|
||||
for_each = var.backend_service_config.log_sample_rate == null ? [] : [""]
|
||||
content {
|
||||
enable = true
|
||||
sample_rate = var.backend_service_config.log_sample_rate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "https" {
|
||||
provider = google-beta
|
||||
count = (
|
||||
var.health_check == null && local.health_check_type == "https" ? 1 : 0
|
||||
)
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
|
||||
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
|
||||
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
|
||||
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
|
||||
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
|
||||
|
||||
https_health_check {
|
||||
host = try(var.health_check_config.check.host, null)
|
||||
port = try(var.health_check_config.check.port, null)
|
||||
port_name = try(var.health_check_config.check.port_name, null)
|
||||
port_specification = try(var.health_check_config.check.port_specification, null)
|
||||
proxy_header = try(var.health_check_config.check.proxy_header, null)
|
||||
request_path = try(var.health_check_config.check.request_path, null)
|
||||
response = try(var.health_check_config.check.response, null)
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = try(var.health_check_config.logging, false) ? [""] : []
|
||||
dynamic "subsetting" {
|
||||
for_each = var.backend_service_config.enable_subsetting == true ? [""] : []
|
||||
content {
|
||||
enable = true
|
||||
policy = "CONSISTENT_HASH_SUBSETTING"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "tcp" {
|
||||
provider = google-beta
|
||||
count = (
|
||||
var.health_check == null && local.health_check_type == "tcp" ? 1 : 0
|
||||
)
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
|
||||
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
|
||||
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
|
||||
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
|
||||
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
|
||||
|
||||
tcp_health_check {
|
||||
port = try(var.health_check_config.check.port, null)
|
||||
port_name = try(var.health_check_config.check.port_name, null)
|
||||
port_specification = try(var.health_check_config.check.port_specification, null)
|
||||
proxy_header = try(var.health_check_config.check.proxy_header, null)
|
||||
request = try(var.health_check_config.check.request, null)
|
||||
response = try(var.health_check_config.check.response, null)
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = try(var.health_check_config.logging, false) ? [""] : []
|
||||
content {
|
||||
enable = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "ssl" {
|
||||
provider = google-beta
|
||||
count = (
|
||||
var.health_check == null && local.health_check_type == "ssl" ? 1 : 0
|
||||
)
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
|
||||
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
|
||||
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
|
||||
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
|
||||
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
|
||||
|
||||
ssl_health_check {
|
||||
port = try(var.health_check_config.check.port, null)
|
||||
port_name = try(var.health_check_config.check.port_name, null)
|
||||
port_specification = try(var.health_check_config.check.port_specification, null)
|
||||
proxy_header = try(var.health_check_config.check.proxy_header, null)
|
||||
request = try(var.health_check_config.check.request, null)
|
||||
response = try(var.health_check_config.check.response, null)
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = try(var.health_check_config.logging, false) ? [""] : []
|
||||
content {
|
||||
enable = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_health_check" "http2" {
|
||||
provider = google-beta
|
||||
count = (
|
||||
var.health_check == null && local.health_check_type == "http2" ? 1 : 0
|
||||
)
|
||||
project = var.project_id
|
||||
name = var.name
|
||||
description = "Terraform managed."
|
||||
|
||||
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
|
||||
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
|
||||
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
|
||||
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
|
||||
|
||||
http2_health_check {
|
||||
host = try(var.health_check_config.check.host, null)
|
||||
port = try(var.health_check_config.check.port, null)
|
||||
port_name = try(var.health_check_config.check.port_name, null)
|
||||
port_specification = try(var.health_check_config.check.port_specification, null)
|
||||
proxy_header = try(var.health_check_config.check.proxy_header, null)
|
||||
request_path = try(var.health_check_config.check.request_path, null)
|
||||
response = try(var.health_check_config.check.response, null)
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = try(var.health_check_config.logging, false) ? [""] : []
|
||||
content {
|
||||
enable = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,17 +14,17 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
output "backend" {
|
||||
output "backend_service" {
|
||||
description = "Backend resource."
|
||||
value = google_compute_region_backend_service.default
|
||||
}
|
||||
|
||||
output "backend_id" {
|
||||
output "backend_service_id" {
|
||||
description = "Backend id."
|
||||
value = google_compute_region_backend_service.default.id
|
||||
}
|
||||
|
||||
output "backend_self_link" {
|
||||
output "backend_service_self_link" {
|
||||
description = "Backend self link."
|
||||
value = google_compute_region_backend_service.default.self_link
|
||||
}
|
||||
|
@ -49,6 +49,11 @@ output "forwarding_rule_self_link" {
|
|||
value = google_compute_forwarding_rule.default.self_link
|
||||
}
|
||||
|
||||
output "groups" {
|
||||
description = "Optional unmanaged instance group resources."
|
||||
value = google_compute_instance_group.unmanaged
|
||||
}
|
||||
|
||||
output "group_self_links" {
|
||||
description = "Optional unmanaged instance group self links."
|
||||
value = {
|
||||
|
@ -56,22 +61,17 @@ output "group_self_links" {
|
|||
}
|
||||
}
|
||||
|
||||
output "groups" {
|
||||
description = "Optional unmanaged instance group resources."
|
||||
value = google_compute_instance_group.unmanaged
|
||||
}
|
||||
|
||||
output "health_check" {
|
||||
description = "Auto-created health-check resource."
|
||||
value = local.health_check_resource
|
||||
value = try(google_compute_health_check.default.0, null)
|
||||
}
|
||||
|
||||
output "health_check_self_id" {
|
||||
description = "Auto-created health-check self id."
|
||||
value = try(local.health_check_resource.id, null)
|
||||
value = try(google_compute_health_check.default.0.id, null)
|
||||
}
|
||||
|
||||
output "health_check_self_link" {
|
||||
description = "Auto-created health-check self link."
|
||||
value = try(local.health_check_resource.self_link, null)
|
||||
value = try(google_compute_health_check.default.0.self_link, null)
|
||||
}
|
||||
|
|
|
@ -20,33 +20,62 @@ variable "address" {
|
|||
default = null
|
||||
}
|
||||
|
||||
variable "backend_config" {
|
||||
description = "Optional backend configuration."
|
||||
variable "backend_service_config" {
|
||||
description = "Backend service level configuration."
|
||||
type = object({
|
||||
session_affinity = string
|
||||
timeout_sec = number
|
||||
connection_draining_timeout_sec = number
|
||||
connection_draining_timeout_sec = optional(number)
|
||||
connection_tracking = optional(object({
|
||||
idle_timeout_sec = optional(number)
|
||||
persist_conn_on_unhealthy = optional(string)
|
||||
track_per_session = optional(bool)
|
||||
}))
|
||||
enable_subsetting = optional(bool)
|
||||
failover_config = optional(object({
|
||||
disable_conn_drain = optional(bool)
|
||||
drop_traffic_if_unhealthy = optional(bool)
|
||||
ratio = optional(number)
|
||||
}))
|
||||
log_sample_rate = optional(number)
|
||||
session_affinity = optional(string)
|
||||
timeout_sec = optional(number)
|
||||
})
|
||||
default = null
|
||||
default = {}
|
||||
nullable = false
|
||||
validation {
|
||||
condition = contains(
|
||||
[
|
||||
"NONE", "CLIENT_IP", "CLIENT_IP_NO_DESTINATION",
|
||||
"CLIENT_IP_PORT_PROTO", "CLIENT_IP_PROTO"
|
||||
],
|
||||
coalesce(var.backend_service_config.session_affinity, "NONE")
|
||||
)
|
||||
error_message = "Invalid session affinity value."
|
||||
}
|
||||
}
|
||||
|
||||
variable "backends" {
|
||||
description = "Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'."
|
||||
type = list(object({
|
||||
failover = bool
|
||||
group = string
|
||||
balancing_mode = string
|
||||
balancing_mode = optional(string, "CONNECTION")
|
||||
description = optional(string, "Terraform managed.")
|
||||
failover = optional(bool, false)
|
||||
}))
|
||||
default = []
|
||||
nullable = false
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for b in var.backends : contains(
|
||||
["CONNECTION", "UTILIZATION"], coalesce(b.balancing_mode, "CONNECTION")
|
||||
)])
|
||||
error_message = "When specified balancing mode needs to be 'CONNECTION' or 'UTILIZATION'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "failover_config" {
|
||||
description = "Optional failover configuration."
|
||||
type = object({
|
||||
disable_connection_drain = bool
|
||||
drop_traffic_if_unhealthy = bool
|
||||
ratio = number
|
||||
})
|
||||
default = null
|
||||
variable "description" {
|
||||
description = "Optional description used for resources."
|
||||
type = string
|
||||
default = "Terraform managed."
|
||||
}
|
||||
|
||||
variable "global_access" {
|
||||
|
@ -58,11 +87,12 @@ variable "global_access" {
|
|||
variable "group_configs" {
|
||||
description = "Optional unmanaged groups to create. Can be referenced in backends via outputs."
|
||||
type = map(object({
|
||||
instances = list(string)
|
||||
named_ports = map(number)
|
||||
zone = string
|
||||
instances = optional(list(string), [])
|
||||
named_ports = optional(map(number), {})
|
||||
}))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "health_check" {
|
||||
|
@ -72,20 +102,76 @@ variable "health_check" {
|
|||
}
|
||||
|
||||
variable "health_check_config" {
|
||||
description = "Configuration of the auto-created helth check."
|
||||
description = "Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage."
|
||||
type = object({
|
||||
type = string # http https tcp ssl http2
|
||||
check = map(any) # actual health check block attributes
|
||||
config = map(number) # interval, thresholds, timeout
|
||||
logging = bool
|
||||
check_interval_sec = optional(number)
|
||||
description = optional(string, "Terraform managed.")
|
||||
enable_logging = optional(bool, false)
|
||||
healthy_threshold = optional(number)
|
||||
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 = {
|
||||
type = "http"
|
||||
check = {
|
||||
tcp = {
|
||||
port_specification = "USE_SERVING_PORT"
|
||||
}
|
||||
config = {}
|
||||
logging = false
|
||||
}
|
||||
validation {
|
||||
condition = (
|
||||
(try(var.health_check_config.grpc, null) == null ? 0 : 1) +
|
||||
(try(var.health_check_config.http, null) == null ? 0 : 1) +
|
||||
(try(var.health_check_config.tcp, null) == null ? 0 : 1) <= 1
|
||||
)
|
||||
error_message = "Only one health check type can be configured at a time."
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,11 +186,6 @@ variable "name" {
|
|||
type = string
|
||||
}
|
||||
|
||||
variable "network" {
|
||||
description = "Network used for resources."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ports" {
|
||||
description = "Comma-separated ports, leave null to use all ports."
|
||||
type = list(string)
|
||||
|
@ -133,7 +214,11 @@ variable "service_label" {
|
|||
default = null
|
||||
}
|
||||
|
||||
variable "subnetwork" {
|
||||
description = "Subnetwork used for the forwarding rule."
|
||||
type = string
|
||||
variable "vpc_config" {
|
||||
description = "VPC-level configuration."
|
||||
type = object({
|
||||
network = string
|
||||
subnetwork = string
|
||||
})
|
||||
nullable = false
|
||||
}
|
||||
|
|
|
@ -18,17 +18,17 @@ module "test" {
|
|||
source = "../../../../modules/net-ilb"
|
||||
project_id = "my-project"
|
||||
region = "europe-west1"
|
||||
name = "ilb-test"
|
||||
vpc_config = {
|
||||
network = "default"
|
||||
subnetwork = "default"
|
||||
name = "ilb-test"
|
||||
labels = {}
|
||||
}
|
||||
address = var.address
|
||||
backend_service_config = var.backend_service_config
|
||||
backends = var.backends
|
||||
backend_config = var.backend_config
|
||||
failover_config = var.failover_config
|
||||
description = var.description
|
||||
global_access = var.global_access
|
||||
health_check = var.health_check
|
||||
health_check_config = var.health_check_config
|
||||
group_configs = var.group_configs
|
||||
ports = var.ports
|
||||
protocol = var.protocol
|
||||
service_label = var.service_label
|
||||
|
|
|
@ -19,30 +19,20 @@ variable "address" {
|
|||
default = null
|
||||
}
|
||||
|
||||
variable "backend_service_config" {
|
||||
description = "Backend service level configuration."
|
||||
type = any
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "backends" {
|
||||
type = list(object({
|
||||
failover = bool
|
||||
group = string
|
||||
balancing_mode = string
|
||||
}))
|
||||
type = any
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "backend_config" {
|
||||
type = object({
|
||||
session_affinity = string
|
||||
timeout_sec = number
|
||||
connection_draining_timeout_sec = number
|
||||
})
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "failover_config" {
|
||||
type = object({
|
||||
disable_connection_drain = bool
|
||||
drop_traffic_if_unhealthy = bool
|
||||
ratio = number
|
||||
})
|
||||
default = null
|
||||
variable "description" {
|
||||
type = string
|
||||
default = "Terraform managed."
|
||||
}
|
||||
|
||||
variable "global_access" {
|
||||
|
@ -50,26 +40,9 @@ variable "global_access" {
|
|||
default = null
|
||||
}
|
||||
|
||||
variable "health_check" {
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "health_check_config" {
|
||||
type = object({
|
||||
type = string # http https tcp ssl http2
|
||||
check = map(any) # actual health check block attributes
|
||||
config = map(number) # interval, thresholds, timeout
|
||||
logging = bool
|
||||
})
|
||||
default = {
|
||||
type = "http"
|
||||
check = {
|
||||
port_specification = "USE_SERVING_PORT"
|
||||
}
|
||||
config = {}
|
||||
logging = false
|
||||
}
|
||||
variable "group_configs" {
|
||||
type = any
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "ports" {
|
||||
|
|
|
@ -29,7 +29,7 @@ def test_defaults(plan_runner):
|
|||
assert backend['backend'][0]['group'] == 'foo'
|
||||
health_check = resources['google_compute_health_check']
|
||||
for k, v in health_check.items():
|
||||
if k == 'http_health_check':
|
||||
if k == 'tcp_health_check':
|
||||
assert len(v) == 1
|
||||
assert v[0]['port_specification'] == 'USE_SERVING_PORT'
|
||||
elif k.endswith('_health_check'):
|
||||
|
@ -38,12 +38,14 @@ def test_defaults(plan_runner):
|
|||
|
||||
def test_forwarding_rule(plan_runner):
|
||||
"Test forwarding rule variables."
|
||||
_, resources = plan_runner(backends=_BACKENDS,
|
||||
global_access='true',
|
||||
_, resources = plan_runner(backends=_BACKENDS, global_access='true',
|
||||
ports="[80]")
|
||||
assert len(resources) == 3
|
||||
values = [r['values'] for r in resources if r['type']
|
||||
== 'google_compute_forwarding_rule'][0]
|
||||
values = [
|
||||
r['values']
|
||||
for r in resources
|
||||
if r['type'] == 'google_compute_forwarding_rule'
|
||||
][0]
|
||||
assert not values['all_ports']
|
||||
assert values['ports'] == ['80']
|
||||
assert values['allow_global_access']
|
||||
|
|
Loading…
Reference in New Issue