# Variables ==================================================================== variable "name_prefix" { description = "Prefix prepended to resource names created by this module." type = string validation { condition = length(trimspace(var.name_prefix)) > 0 error_message = "name_prefix must not be empty." } } variable "name_suffix" { description = "Suffix appended to the load balancer resource name to distinguish it within name_prefix." type = string validation { condition = length(trimspace(var.name_suffix)) > 0 error_message = "name_suffix must not be empty." } } variable "tags" { description = "Tags applied to all resources in this module." type = map(string) default = {} } variable "load_balancer_type" { description = "Load balancer type — application or network." type = string default = "application" validation { condition = contains(["application", "network"], var.load_balancer_type) error_message = "load_balancer_type must be application or network." } } variable "internal" { description = "Create an internal (non-internet-facing) load balancer." type = bool default = false } variable "subnet_ids" { description = "Subnet IDs for the load balancer. Must span at least two AZs." type = list(string) validation { condition = length(var.subnet_ids) >= 2 error_message = "subnet_ids must include at least two subnets across different AZs." } } variable "security_group_ids" { description = "Security group IDs to attach to the load balancer's ENIs. Supported on ALB always, and on NLB in regions/accounts with the 2023 NLB security groups feature enabled." type = list(string) default = [] } variable "cross_zone_load_balancing" { description = "Enable cross-zone load balancing. Valid for NLB only — ALB always has this enabled and it is not configurable." type = bool default = true } variable "access_logs_bucket" { description = "S3 bucket for access logs (optional)." type = string default = null } variable "access_logs_prefix" { description = "S3 prefix for access logs." type = string default = "lb" } variable "deletion_protection" { description = "Enable deletion protection." type = bool default = true } variable "idle_timeout" { description = "Idle timeout in seconds. Valid for ALB only — NLB connections do not have a configurable idle timeout." type = number default = 60 } variable "waf_web_acl_arn" { description = "WAF Web ACL ARN to associate with the load balancer. Valid for ALB only — WAFv2 does not support NLB as an association target." type = string default = null } variable "target_groups" { description = <<-EOT Map of target group definitions. - name_suffix is combined with name_prefix and region to build the target group name. - protocol must be TCP/UDP/TCP_UDP for NLB target groups, HTTP/HTTPS for ALB. - stickiness.type must be source_ip for NLB, lb_cookie or app_cookie for ALB. - targets is a map of instance IDs (target_type = "instance") or IP addresses (target_type = "ip") to attach. port overrides the target group's port for that specific target; leave null to use the target group's port. EOT type = map(object({ name_suffix = string port = number protocol = string target_type = optional(string, "instance") vpc_id = string deregistration_delay = optional(number, 30) tags = optional(map(string), {}) targets = optional(map(object({ id = string port = optional(number, null) })), {}) health_check = optional(object({ enabled = optional(bool, true) path = optional(string, "/health") protocol = optional(string, "HTTP") matcher = optional(string, "200") interval = optional(number, 30) timeout = optional(number, 5) healthy_threshold = optional(number, 2) unhealthy_threshold = optional(number, 2) }), {}) stickiness = optional(object({ enabled = optional(bool, false) cookie_duration = optional(number, 86400) type = optional(string, "lb_cookie") }), null) })) default = {} validation { condition = alltrue([ for k, v in var.target_groups : v.deregistration_delay >= 0 && v.deregistration_delay <= 3600 ]) error_message = "deregistration_delay must be between 0 and 3600 seconds." } validation { condition = alltrue([ for k, v in var.target_groups : length(trimspace(v.name_suffix)) > 0 ]) error_message = "Every target group must set a non-empty name_suffix." } validation { condition = alltrue([ for k, v in var.target_groups : contains(["HTTP", "HTTPS", "TCP", "UDP", "TCP_UDP", "TLS", "GENEVE"], v.protocol) ]) error_message = "Target group protocol must be one of HTTP, HTTPS, TCP, UDP, TCP_UDP, TLS, GENEVE." } validation { condition = alltrue([ for k, v in var.target_groups : v.stickiness == null || contains(["lb_cookie", "app_cookie", "source_ip"], v.stickiness.type) ]) error_message = "stickiness.type must be lb_cookie, app_cookie, or source_ip." } } variable "listeners" { description = <<-EOT Map of load balancer listener definitions. - redirect actions are only valid on ALB listeners — NLB does not support the redirect action type. - certificate_arn is only meaningful for HTTPS/TLS protocol listeners. EOT type = map(object({ port = number protocol = string certificate_arn = optional(string, null) ssl_policy = optional(string, "ELBSecurityPolicy-TLS13-1-2-2021-06") default_action_type = optional(string, "forward") target_group_key = optional(string, null) redirect = optional(object({ port = optional(string, "443") protocol = optional(string, "HTTPS") status_code = optional(string, "HTTP_301") }), null) })) default = {} validation { condition = alltrue([ for k, v in var.listeners : contains(["HTTP", "HTTPS", "TCP", "UDP", "TCP_UDP", "TLS"], v.protocol) ]) error_message = "Listener protocol must be one of HTTP, HTTPS, TCP, UDP, TCP_UDP, TLS." } validation { condition = alltrue([ for k, v in var.listeners : !(v.protocol == "HTTPS" || v.protocol == "TLS") || v.certificate_arn != null ]) error_message = "Listeners using HTTPS or TLS protocol must set certificate_arn." } validation { condition = alltrue([ for k, v in var.listeners : v.redirect != null || v.target_group_key != null ]) error_message = "Every listener must set either target_group_key or redirect." } }