-
Notifications
You must be signed in to change notification settings - Fork 1
/
http.tf
164 lines (143 loc) · 4.6 KB
/
http.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
locals {
# Filter services that expose a HTTP port
http_services = {
for service_name, service in local.services:
service_name => service
if service.http != null
}
# Map service names to target group names
target_group_names = {
for service_name, service in local.http_services:
service_name => "${local.common_name}-${service.name}"
}
# Standard limit of rules per ALB listener
rules_count_limit = 100
# Distinct load balancers
load_balancer_names = toset(values(local.http_services)[*].http.load_balancer_name)
# Map of services to the load balancer listeners they will be bound to
listener_arns = {
for service_name, service in local.http_services:
service_name => data.aws_lb_listener.https[service.http.load_balancer_name].arn
}
}
data "aws_lb" "main" {
for_each = local.load_balancer_names
name = each.key
}
data "aws_lb_listener" "https" {
for_each = local.load_balancer_names
load_balancer_arn = data.aws_lb.main[each.key].arn
port = 443
}
resource "aws_lb_target_group" "http" {
/*
The Target Groups to contain EC2 instances in HTTP services
*/
for_each = local.http_services
vpc_id = local.vpc_id
port = each.value.http.port
deregistration_delay = 30
protocol = "HTTP"
target_type = each.value.is_fargate ? "ip" : "instance"
tags = {
Name = local.target_group_names[each.key]
}
health_check {
interval = 30
path = each.value.http.health_check.path
unhealthy_threshold = 2
healthy_threshold = 2
port = each.value.is_fargate ? each.value.http.port : "traffic-port"
matcher = join(",", each.value.http.health_check.status_codes)
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_lb_listener_rule" "main" {
/*
Rules for the load balancer listener
*/
for_each = local.http_services
listener_arn = local.listener_arns[each.key]
priority = random_integer.rule_priority[each.key].result
action {
type = "forward"
target_group_arn = aws_lb_target_group.http[each.key].arn
}
# Match hostnames
dynamic "condition" {
for_each = each.value.http.listener_rule.hostnames == null ? [] : [true]
content {
host_header { values = each.value.http.listener_rule.hostnames }
}
}
# Match path patterns
dynamic "condition" {
for_each = each.value.http.listener_rule.paths == null ? [] : [true]
content {
path_pattern { values = each.value.http.listener_rule.paths }
}
}
# Match HTTP headers
dynamic "condition" {
for_each = coalesce(each.value.http.listener_rule.headers, {})
content {
http_header {
http_header_name = condition.key
values = condition.value
}
}
}
# HTTP request methods
dynamic "condition" {
for_each = each.value.http.listener_rule.methods == null ? [] : [true]
content {
http_request_method { values = each.value.http.listener_rule.methods }
}
}
# URL query string
dynamic "condition" {
for_each = coalesce(each.value.http.listener_rule.query_string, {})
content {
query_string {
key = condition.key
value = condition.value
}
}
}
# Source IP address CIDR blocks
dynamic "condition" {
for_each = each.value.http.listener_rule.source_ips == null ? [] : [true]
content {
source_ip { values = each.value.http.listener_rule.source_ips }
}
}
}
resource "random_integer" "rule_priority" {
/*
A number to manage the priority numbers to use in ALB rules without a path
ALBv2 does not sort rules by specificity; rather, it sorts them by a priority
number from 1 to 50000. Also, the default limit of rules per listener is 100.
This resource manages a random number in the first 40000 positions for rules
with paths, or in the remaining 10000 for rules without any path.
More:
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-update-rules.html
*/
for_each = {
for service_name, service in local.http_services:
service_name => merge(service, {
priority_level = 6 - sum([
service.http.listener_rule.hostnames == null ? 0 : 1,
service.http.listener_rule.paths == null ? 0 : 1,
service.http.listener_rule.headers == null ? 0 : 1,
service.http.listener_rule.methods == null ? 0 : 1,
service.http.listener_rule.query_string == null ? 0 : 1,
service.http.listener_rule.source_ips == null ? 0 : 1,
])
})
}
min = each.value.priority_level * floor(50000 / 6)
max = each.value.priority_level * floor(50000 / 6) + floor(50000 / 6)
keepers = { listener_arn = data.aws_lb_listener.https[each.value.http.load_balancer_name].arn }
}