From 05632606781fc6073b4360c667748e8f96f91a21 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 2 Nov 2022 18:05:20 +0100 Subject: [PATCH] Refactor ILB module for Terraform 1.3 (#941) * wip * wip * wip * backport health check to compute-mig * align blueprints and fast * fix blueprints * tfdoc --- .../data-solutions/sqlserver-alwayson/main.tf | 67 +++-- .../data-solutions/sqlserver-alwayson/vpc.tf | 88 +++--- blueprints/networking/filtering-proxy/main.tf | 20 +- .../networking/ilb-next-hop/gateways.tf | 48 ++-- fast/stages/02-networking-nva/nva.tf | 44 +-- modules/compute-mig/README.md | 26 +- modules/compute-mig/health-check.tf | 25 +- modules/compute-mig/main.tf | 2 +- modules/compute-mig/outputs.tf | 2 +- modules/compute-mig/variables.tf | 28 +- modules/net-ilb/README.md | 68 ++--- modules/net-ilb/groups.tf | 33 +++ modules/net-ilb/health-check.tf | 119 ++++++++ modules/net-ilb/main.tf | 272 ++++-------------- modules/net-ilb/outputs.tf | 22 +- modules/net-ilb/variables.tf | 157 +++++++--- tests/modules/net_ilb/fixture/main.tf | 34 +-- tests/modules/net_ilb/fixture/variables.tf | 55 +--- tests/modules/net_ilb/test_plan.py | 12 +- 19 files changed, 619 insertions(+), 503 deletions(-) create mode 100644 modules/net-ilb/groups.tf create mode 100644 modules/net-ilb/health-check.tf diff --git a/blueprints/data-solutions/sqlserver-alwayson/main.tf b/blueprints/data-solutions/sqlserver-alwayson/main.tf index 3d391c5f..6485b46d 100644 --- a/blueprints/data-solutions/sqlserver-alwayson/main.tf +++ b/blueprints/data-solutions/sqlserver-alwayson/main.tf @@ -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 - - 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) + 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 + 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" { diff --git a/blueprints/data-solutions/sqlserver-alwayson/vpc.tf b/blueprints/data-solutions/sqlserver-alwayson/vpc.tf index dbbf38a7..d3e816cb 100644 --- a/blueprints/data-solutions/sqlserver-alwayson/vpc.tf +++ b/blueprints/data-solutions/sqlserver-alwayson/vpc.tf @@ -15,26 +15,36 @@ # 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 + internal_addresses = merge( + local.listeners, + local.node_ips, + { + "${local.prefix}cluster" = { + region = var.region + subnetwork = local.subnetwork + } + (local.witness_netbios_name) = { + region = var.region + subnetwork = local.subnetwork + } } + ) + internal_address_ips = { + for k, v in module.ip-addresses.internal_addresses : + k => v.address } - 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) = { + listeners = { + for aog in var.always_on_groups : "${local.prefix}lb-${aog}" => { region = var.region subnetwork = local.subnetwork } - (local.witness_netbios_name) = { + } + node_ips = { + for node_name in local.node_netbios_names : node_name => { region = var.region subnetwork = local.subnetwork } - }, local.listeners, local.node_ips) + } } 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 - + 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 - network = local.network - subnetwork = local.subnetwork - + source = "../../../modules/net-ilb" + for_each = toset(var.always_on_groups) + project_id = var.project_id + region = var.region + 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" + group = node.group.self_link }] - 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 + } } } diff --git a/blueprints/networking/filtering-proxy/main.tf b/blueprints/networking/filtering-proxy/main.tf index ca998bf9..eef3bf2d 100644 --- a/blueprints/networking/filtering-proxy/main.tf +++ b/blueprints/networking/filtering-proxy/main.tf @@ -199,20 +199,20 @@ module "squid-ilb" { project_id = module.project-host.project_id region = var.region name = "squid-ilb" - service_label = "squid-ilb" - network = module.vpc.self_link - subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"] ports = [3128] + service_label = "squid-ilb" + vpc_config = { + network = module.vpc.self_link + subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"] + } backends = [{ - failover = false - group = module.squid-mig.0.group_manager.instance_group - balancing_mode = "CONNECTION" + group = module.squid-mig.0.group_manager.instance_group }] health_check_config = { - type = "tcp" - check = { port = 3128 } - config = {} - logging = true + enable_logging = true + tcp = { + port = 3128 + } } } diff --git a/blueprints/networking/ilb-next-hop/gateways.tf b/blueprints/networking/ilb-next-hop/gateways.tf index e5a7fa25..df066484 100644 --- a/blueprints/networking/ilb-next-hop/gateways.tf +++ b/blueprints/networking/ilb-next-hop/gateways.tf @@ -62,22 +62,22 @@ module "ilb-left" { project_id = module.project.project_id region = var.region name = "${local.prefix}ilb-left" - network = module.vpc-left.self_link - subnetwork = values(module.vpc-left.subnet_self_links)[0] - address = local.addresses.ilb-left - ports = null - backend_config = { - session_affinity = var.ilb_session_affinity - timeout_sec = null - connection_draining_timeout_sec = null + vpc_config = { + network = module.vpc-left.self_link + subnetwork = values(module.vpc-left.subnet_self_links)[0] + } + address = local.addresses.ilb-left + backend_service_config = { + session_affinity = var.ilb_session_affinity } backends = [for z, mod in module.gw : { - failover = false - group = mod.group.self_link - balancing_mode = "CONNECTION" + group = mod.group.self_link }] 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" - network = module.vpc-right.self_link - subnetwork = values(module.vpc-right.subnet_self_links)[0] - address = local.addresses.ilb-right - ports = null - backend_config = { - session_affinity = var.ilb_session_affinity - timeout_sec = null - connection_draining_timeout_sec = null + vpc_config = { + network = module.vpc-right.self_link + subnetwork = values(module.vpc-right.subnet_self_links)[0] + } + address = local.addresses.ilb-right + backend_service_config = { + session_affinity = var.ilb_session_affinity } backends = [for z, mod in module.gw : { - failover = false - group = mod.group.self_link - balancing_mode = "CONNECTION" + group = mod.group.self_link }] health_check_config = { - type = "tcp", check = { port = 22 }, config = {}, logging = true + enable_logging = true + tcp = { + port = 22 + } } } diff --git a/fast/stages/02-networking-nva/nva.tf b/fast/stages/02-networking-nva/nva.tf index d0afbd72..f4f7b9e5 100644 --- a/fast/stages/02-networking-nva/nva.tf +++ b/fast/stages/02-networking-nva/nva.tf @@ -120,16 +120,20 @@ module "ilb-nva-untrusted" { name = "nva-untrusted-${each.value.0}" service_label = var.prefix global_access = true - 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 - group = module.nva-mig[key].group_manager.instance_group - balancing_mode = "CONNECTION" - } if local.nva_locality[key].region == each.key] + 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 : { + group = module.nva-mig[key].group_manager.instance_group + } 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 - 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 - group = module.nva-mig[key].group_manager.instance_group - balancing_mode = "CONNECTION" - } if local.nva_locality[key].region == each.key] + 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 : { + group = module.nva-mig[key].group_manager.instance_group + } 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 + } } } diff --git a/modules/compute-mig/README.md b/modules/compute-mig/README.md index 4e5b5a45..895f0517 100644 --- a/modules/compute-mig/README.md +++ b/modules/compute-mig/README.md @@ -417,25 +417,25 @@ module "nginx-mig" { | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [instance_template](variables.tf#L150) | Instance template for the default version. | string | ✓ | | -| [location](variables.tf#L155) | Compute zone or region. | string | ✓ | | -| [name](variables.tf#L160) | Managed group name. | string | ✓ | | -| [project_id](variables.tf#L171) | Project id. | string | ✓ | | +| [instance_template](variables.tf#L174) | Instance template for the default version. | string | ✓ | | +| [location](variables.tf#L179) | Compute zone or region. | string | ✓ | | +| [name](variables.tf#L184) | Managed group name. | string | ✓ | | +| [project_id](variables.tf#L195) | Project id. | string | ✓ | | | [all_instances_config](variables.tf#L17) | Metadata and labels set to all instances in the group. | object({…}) | | null | | [auto_healing_policies](variables.tf#L26) | Auto-healing policies for this group. | object({…}) | | null | | [autoscaler_config](variables.tf#L35) | Optional autoscaler configuration. | object({…}) | | null | | [default_version_name](variables.tf#L83) | Name used for the default version. | string | | "default" | | [description](variables.tf#L89) | Optional description used for all resources managed by this module. | string | | "Terraform managed." | | [distribution_policy](variables.tf#L95) | DIstribution policy for regional MIG. | object({…}) | | null | -| [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. | object({…}) | | null | -| [named_ports](variables.tf#L165) | Named ports. | map(number) | | null | -| [stateful_config](variables.tf#L183) | Stateful configuration for individual instances. | map(object({…})) | | {} | -| [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. | map(bool) | | {} | -| [target_pools](variables.tf#L202) | Optional list of URLs for target pools to which new instances in the group are added. | list(string) | | [] | -| [target_size](variables.tf#L208) | Group target size, leave null when using an autoscaler. | number | | null | -| [update_policy](variables.tf#L214) | Update policy. Minimal action and type are required. | object({…}) | | null | -| [versions](variables.tf#L235) | Additional application versions, target_size is optional. | map(object({…})) | | {} | -| [wait_for_instances](variables.tf#L248) | Wait for all instances to be created/updated before returning. | object({…}) | | null | +| [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. | object({…}) | | null | +| [named_ports](variables.tf#L189) | Named ports. | map(number) | | null | +| [stateful_config](variables.tf#L207) | Stateful configuration for individual instances. | map(object({…})) | | {} | +| [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. | map(bool) | | {} | +| [target_pools](variables.tf#L226) | Optional list of URLs for target pools to which new instances in the group are added. | list(string) | | [] | +| [target_size](variables.tf#L232) | Group target size, leave null when using an autoscaler. | number | | null | +| [update_policy](variables.tf#L238) | Update policy. Minimal action and type are required. | object({…}) | | null | +| [versions](variables.tf#L259) | Additional application versions, target_size is optional. | map(object({…})) | | {} | +| [wait_for_instances](variables.tf#L272) | Wait for all instances to be created/updated before returning. | object({…}) | | null | ## Outputs diff --git a/modules/compute-mig/health-check.tf b/modules/compute-mig/health-check.tf index 9a5d8d1f..4a4ed40d 100644 --- a/modules/compute-mig/health-check.tf +++ b/modules/compute-mig/health-check.tf @@ -17,25 +17,16 @@ # 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 && - 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 = 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" "autohealing" { +resource "google_compute_health_check" "default" { provider = google-beta count = local.hc != null ? 1 : 0 project = var.project_id diff --git a/modules/compute-mig/main.tf b/modules/compute-mig/main.tf index 92738995..35f255a6 100644 --- a/modules/compute-mig/main.tf +++ b/modules/compute-mig/main.tf @@ -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 = ( diff --git a/modules/compute-mig/outputs.tf b/modules/compute-mig/outputs.tf index a7be7d2e..41b20c1f 100644 --- a/modules/compute-mig/outputs.tf +++ b/modules/compute-mig/outputs.tf @@ -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 ) } diff --git a/modules/compute-mig/variables.tf b/modules/compute-mig/variables.tf index 299dacc8..056bd198 100644 --- a/modules/compute-mig/variables.tf +++ b/modules/compute-mig/variables.tf @@ -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 diff --git a/modules/net-ilb/README.md b/modules/net-ilb/README.md index 5637f0ef..9916f736 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-ilb/README.md @@ -23,11 +23,13 @@ module "ilb" { region = "europe-west1" name = "ilb-test" service_label = "ilb-test" - network = var.vpc.self_link - subnetwork = var.subnet.self_link + 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" - network = var.vpc.self_link - subnetwork = var.subnet.self_link + 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'. | list(object({…})) | ✓ | | -| [name](variables.tf#L98) | Name used for all resources. | string | ✓ | | -| [network](variables.tf#L103) | Network used for resources. | string | ✓ | | -| [project_id](variables.tf#L114) | Project id where resources will be created. | string | ✓ | | -| [region](variables.tf#L125) | GCP region. | string | ✓ | | -| [subnetwork](variables.tf#L136) | Subnetwork used for the forwarding rule. | string | ✓ | | +| [name](variables.tf#L184) | Name used for all resources. | string | ✓ | | +| [project_id](variables.tf#L195) | Project id where resources will be created. | string | ✓ | | +| [region](variables.tf#L206) | GCP region. | string | ✓ | | +| [vpc_config](variables.tf#L217) | VPC-level configuration. | object({…}) | ✓ | | | [address](variables.tf#L17) | Optional IP address used for the forwarding rule. | string | | null | -| [backend_config](variables.tf#L23) | Optional backend configuration. | object({…}) | | null | -| [failover_config](variables.tf#L42) | Optional failover configuration. | object({…}) | | null | -| [global_access](variables.tf#L52) | Global access, defaults to false if not set. | bool | | null | -| [group_configs](variables.tf#L58) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | map(object({…})) | | {} | -| [health_check](variables.tf#L68) | Name of existing health check to use, disables auto-created health check. | string | | null | -| [health_check_config](variables.tf#L74) | Configuration of the auto-created helth check. | object({…}) | | {…} | -| [labels](variables.tf#L92) | Labels set on resources. | map(string) | | {} | -| [ports](variables.tf#L108) | Comma-separated ports, leave null to use all ports. | list(string) | | null | -| [protocol](variables.tf#L119) | IP protocol used, defaults to TCP. | string | | "TCP" | -| [service_label](variables.tf#L130) | Optional prefix of the fully qualified forwarding rule name. | string | | null | +| [backend_service_config](variables.tf#L23) | Backend service level configuration. | object({…}) | | {} | +| [backends](variables.tf#L56) | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | list(object({…})) | | [] | +| [description](variables.tf#L75) | Optional description used for resources. | string | | "Terraform managed." | +| [global_access](variables.tf#L81) | Global access, defaults to false if not set. | bool | | null | +| [group_configs](variables.tf#L87) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | map(object({…})) | | {} | +| [health_check](variables.tf#L98) | Name of existing health check to use, disables auto-created health check. | string | | null | +| [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. | object({…}) | | {…} | +| [labels](variables.tf#L178) | Labels set on resources. | map(string) | | {} | +| [ports](variables.tf#L189) | Comma-separated ports, leave null to use all ports. | list(string) | | null | +| [protocol](variables.tf#L200) | IP protocol used, defaults to TCP. | string | | "TCP" | +| [service_label](variables.tf#L211) | Optional prefix of the fully qualified forwarding rule name. | string | | null | ## 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. | | diff --git a/modules/net-ilb/groups.tf b/modules/net-ilb/groups.tf new file mode 100644 index 00000000..fe8bf13d --- /dev/null +++ b/modules/net-ilb/groups.tf @@ -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 + } + } +} diff --git a/modules/net-ilb/health-check.tf b/modules/net-ilb/health-check.tf new file mode 100644 index 00000000..4a4ed40d --- /dev/null +++ b/modules/net-ilb/health-check.tf @@ -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 + } + } +} diff --git a/modules/net-ilb/main.tf b/modules/net-ilb/main.tf index aa4addcc..be4c5786 100644 --- a/modules/net-ilb/main.tf +++ b/modules/net-ilb/main.tf @@ -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." + provider = google-beta + project = var.project_id + region = var.region + 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" - region = var.region - network = var.network - subnetwork = var.subnetwork - ip_address = var.address - ip_protocol = var.protocol # TCP | UDP - ports = var.ports # "nnnnn" or "nnnnn,nnnnn,nnnnn" max 5 - service_label = var.service_label - all_ports = var.ports == null ? true : null + network = var.vpc_config.network + ports = var.ports # "nnnnn" or "nnnnn,nnnnn,nnnnn" max 5 + subnetwork = var.vpc_config.subnetwork allow_global_access = var.global_access - backend_service = google_compute_region_backend_service.default.self_link + labels = var.labels + all_ports = var.ports == null ? true : null + service_label = var.service_label # is_mirroring_collector = false - labels = var.labels } 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] - 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) + provider = google-beta + project = var.project_id + region = var.region + name = var.name + description = var.description + load_balancing_scheme = "INTERNAL" + protocol = var.protocol + 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 + 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 - } - } -} - diff --git a/modules/net-ilb/outputs.tf b/modules/net-ilb/outputs.tf index 55b454e1..3f8eb9e4 100644 --- a/modules/net-ilb/outputs.tf +++ b/modules/net-ilb/outputs.tf @@ -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) } diff --git a/modules/net-ilb/variables.tf b/modules/net-ilb/variables.tf index 638aee52..d2ffc5a6 100644 --- a/modules/net-ilb/variables.tf +++ b/modules/net-ilb/variables.tf @@ -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 = {} + 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 } diff --git a/tests/modules/net_ilb/fixture/main.tf b/tests/modules/net_ilb/fixture/main.tf index c592421f..66346efc 100644 --- a/tests/modules/net_ilb/fixture/main.tf +++ b/tests/modules/net_ilb/fixture/main.tf @@ -15,21 +15,21 @@ */ module "test" { - source = "../../../../modules/net-ilb" - project_id = "my-project" - region = "europe-west1" - network = "default" - subnetwork = "default" - name = "ilb-test" - labels = {} - address = var.address - backends = var.backends - backend_config = var.backend_config - failover_config = var.failover_config - global_access = var.global_access - health_check = var.health_check - health_check_config = var.health_check_config - ports = var.ports - protocol = var.protocol - service_label = var.service_label + source = "../../../../modules/net-ilb" + project_id = "my-project" + region = "europe-west1" + name = "ilb-test" + vpc_config = { + network = "default" + subnetwork = "default" + } + address = var.address + backend_service_config = var.backend_service_config + backends = var.backends + description = var.description + global_access = var.global_access + group_configs = var.group_configs + ports = var.ports + protocol = var.protocol + service_label = var.service_label } diff --git a/tests/modules/net_ilb/fixture/variables.tf b/tests/modules/net_ilb/fixture/variables.tf index b00b49a6..2c2c2fb4 100644 --- a/tests/modules/net_ilb/fixture/variables.tf +++ b/tests/modules/net_ilb/fixture/variables.tf @@ -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" { diff --git a/tests/modules/net_ilb/test_plan.py b/tests/modules/net_ilb/test_plan.py index 722ada3d..9956b331 100644 --- a/tests/modules/net_ilb/test_plan.py +++ b/tests/modules/net_ilb/test_plan.py @@ -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']