# Load balancer =============================================================== resource "aws_lb" "this" { name = local.lb_name load_balancer_type = var.load_balancer_type internal = var.internal subnets = var.subnet_ids security_groups = length(var.security_group_ids) > 0 ? var.security_group_ids : null enable_deletion_protection = var.deletion_protection idle_timeout = local.is_alb ? var.idle_timeout : null enable_cross_zone_load_balancing = local.is_nlb ? var.cross_zone_load_balancing : null dynamic "access_logs" { for_each = var.access_logs_bucket != null ? [true] : [] content { bucket = var.access_logs_bucket prefix = var.access_logs_prefix enabled = true } } tags = merge(var.tags, local.module_tags, { Name = local.lb_name resource-type = "load-balancer" }) lifecycle { postcondition { condition = self.arn != "" error_message = "Load balancer ${self.name} did not receive an ARN after apply." } postcondition { condition = self.dns_name != "" error_message = "Load balancer ${self.name} has no DNS name — check subnet and az coverage." } } } # WAF association -------------------------------------------------------------- # WAFv2 web ACLs only support ALB, API Gateway, and AppSync as targets. resource "aws_wafv2_web_acl_association" "this" { for_each = var.waf_web_acl_arn != null && local.is_alb ? { waf = true } : {} resource_arn = aws_lb.this.arn web_acl_arn = var.waf_web_acl_arn } # Target groups ================================================================ resource "aws_lb_target_group" "this" { for_each = var.target_groups name = local.target_group_names[each.key] port = each.value.port protocol = each.value.protocol target_type = each.value.target_type vpc_id = each.value.vpc_id deregistration_delay = each.value.deregistration_delay health_check { enabled = each.value.health_check.enabled path = each.value.health_check.protocol == "TCP" ? null : each.value.health_check.path protocol = each.value.health_check.protocol matcher = each.value.health_check.protocol == "TCP" ? null : each.value.health_check.matcher interval = each.value.health_check.interval timeout = each.value.health_check.protocol == "TCP" ? null : each.value.health_check.timeout healthy_threshold = each.value.health_check.healthy_threshold unhealthy_threshold = each.value.health_check.unhealthy_threshold } dynamic "stickiness" { for_each = each.value.stickiness != null ? [each.value.stickiness] : [] content { enabled = stickiness.value.enabled cookie_duration = stickiness.value.type == "source_ip" ? null : stickiness.value.cookie_duration type = stickiness.value.type } } tags = merge(var.tags, each.value.tags, local.module_tags, { Name = local.target_group_names[each.key] resource-type = "load-balancer-target-group" }) lifecycle { postcondition { condition = self.arn != "" error_message = "Target group ${self.name} did not receive an ARN after apply." } } } # Target group attachments ======================================================== resource "aws_lb_target_group_attachment" "this" { for_each = local.target_attachments target_group_arn = aws_lb_target_group.this[each.value.target_group_key].arn target_id = each.value.target_id port = each.value.port } # Listeners ====================================================================== resource "aws_lb_listener" "this" { for_each = var.listeners load_balancer_arn = aws_lb.this.arn port = each.value.port protocol = each.value.protocol certificate_arn = each.value.certificate_arn ssl_policy = each.value.certificate_arn != null ? each.value.ssl_policy : null dynamic "default_action" { for_each = each.value.redirect != null ? [] : [true] content { type = each.value.default_action_type target_group_arn = each.value.target_group_key != null ? aws_lb_target_group.this[each.value.target_group_key].arn : null } } dynamic "default_action" { for_each = each.value.redirect != null ? [each.value.redirect] : [] content { type = "redirect" redirect { port = default_action.value.port protocol = default_action.value.protocol status_code = default_action.value.status_code } } } tags = merge(var.tags, local.module_tags, { Name = local.listener_keys[each.key] resource-type = "load-balancer-listener" }) lifecycle { postcondition { condition = self.arn != "" error_message = "Listener on port ${self.port} did not receive an ARN after apply." } } }