Skip to content

Commit d8d3e33

Browse files
authored
feat: Add submodule which ignores changes to backend group (#81)
* feat: Add autogenerated dynamic backends submodule * Add make build command to CONTRIBUTING.md
1 parent e0221c0 commit d8d3e33

File tree

15 files changed

+1158
-5
lines changed

15 files changed

+1158
-5
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@ The following dependencies must be installed on the development system:
1010
- [Google Cloud SDK][google-cloud-sdk]
1111
- [make]
1212

13-
## Generating Documentation for Inputs and Outputs
13+
## Generating Modules
14+
15+
Run `make build` to generate new module code.
16+
17+
### Submodules
18+
The main module Terraform code is stored in the [./autogen](./autogen) folder. Changes should be made there and then reflected into the submodules via `make build`.
19+
20+
### Generating Documentation for Inputs and Outputs
1421

1522
The Inputs and Outputs tables in the READMEs of the root module,
1623
submodules, and example modules are automatically generated based on
1724
the `variables` and `outputs` of the respective modules. These tables
1825
must be refreshed if the module interfaces are changed.
1926

20-
### Execution
21-
22-
Run `make generate_docs` to generate new Inputs and Outputs tables.
23-
2427
## Integration Testing
2528

2629
Integration tests are used to verify the behaviour of the root module,

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ docker_generate_docs:
8080
$(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \
8181
/bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_docs'
8282

83+
## Generate files from autogen
84+
.PHONY: docker_generate_modules
85+
docker_generate_modules:
86+
docker run --rm -it \
87+
-v "$(CURDIR)":/workspace \
88+
$(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \
89+
/bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_modules'
90+
8391
# Alias for backwards compatibility
8492
.PHONY: generate_docs
8593
generate_docs: docker_generate_docs
94+
95+
.PHONY: build
96+
build: docker_generate_modules docker_generate_docs

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Modular Global HTTP Load Balancer for GCE using forwarding rules.
44

5+
If you would like to allow for backend groups to be managed outside Terraform, such as via GKE services, see the [dynamic backends](./modules/dynamic_backends) submodule.
6+
57
### Load Balancer Types
68
* [TCP load balancer](https://github.com/terraform-google-modules/terraform-google-lb)
79
* **HTTP/S load balancer**

autogen/README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Global HTTP Load Balancer Terraform Module
2+
3+
Modular Global HTTP Load Balancer for GCE using forwarding rules.
4+
5+
{% if root %}
6+
If you would like to allow for backend groups to be managed outside Terraform, such as via GKE services, see the [dynamic backends](./modules/dynamic_backends) submodule.
7+
{% elif dynamic_backends %}
8+
This submodule allows for configuring dynamic backend outside Terraform.
9+
As such, any changes to the `backends.groups` variable after creation will be ignored.
10+
{% endif %}
11+
12+
### Load Balancer Types
13+
* [TCP load balancer](https://github.com/terraform-google-modules/terraform-google-lb)
14+
* **HTTP/S load balancer**
15+
* [Internal load balancer](https://github.com/terraform-google-modules/terraform-google-lb-internal)
16+
17+
## Compatibility
18+
19+
This module is meant for use with Terraform 0.12. If you haven't [upgraded](https://www.terraform.io/upgrade-guides/0-12.html) and
20+
need a Terraform 0.11.x-compatible version of this module, the last released version intended for Terraform 0.11.x is
21+
[1.0.10](https://registry.terraform.io/modules/GoogleCloudPlatform/lb-http/google/1.0.10).
22+
23+
## Usage
24+
25+
```HCL
26+
module "gce-lb-http" {
27+
source = "GoogleCloudPlatform/lb-http/google{{ module_path }}"
28+
name = "group-http-lb"
29+
target_tags = [module.mig1.target_tags, module.mig2.target_tags]
30+
backends = {
31+
default = {
32+
description = null
33+
protocol = "HTTP"
34+
port = var.service_port
35+
port_name = var.service_port_name
36+
timeout_sec = 10
37+
connection_draining_timeout_sec = null
38+
enable_cdn = false
39+
40+
health_check = {
41+
check_interval_sec = null
42+
timeout_sec = null
43+
healthy_threshold = null
44+
unhealthy_threshold = null
45+
request_path = "/"
46+
port = var.service_port
47+
host = null
48+
}
49+
50+
groups = [
51+
{
52+
# Each node pool instance group should be added to the backend.
53+
group = var.backend
54+
balancing_mode = null
55+
capacity_scaler = null
56+
description = null
57+
max_connections = null
58+
max_connections_per_instance = null
59+
max_connections_per_endpoint = null
60+
max_rate = null
61+
max_rate_per_instance = null
62+
max_rate_per_endpoint = null
63+
max_utilization = null
64+
},
65+
]
66+
}
67+
}
68+
}
69+
```
70+
71+
## Resources created
72+
73+
**Figure 1.** *diagram of terraform resources*
74+
75+
![architecture diagram](./diagram.png)
76+
77+
## Version
78+
79+
Current version is 3.0. Upgrade guides:
80+
- [1.X -> 2.X](https://www.terraform.io/upgrade-guides/0-12.html)
81+
- [2.X -> 3.0](./docs/upgrading-v2.0.0-v3.0.0.md)
82+
83+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
84+
## Inputs
85+
86+
| Name | Description | Type | Default | Required |
87+
|------|-------------|:----:|:-----:|:-----:|
88+
| address | IP address self link | string | `"null"` | no |
89+
| backends | Map backend indices to list of backend maps. | object | n/a | yes |
90+
| cdn | Set to `true` to enable cdn on backend. | bool | `"false"` | no |
91+
| certificate | Content of the SSL certificate. Required if `ssl` is `true` and `ssl_certificates` is empty. | string | `"null"` | no |
92+
| create\_address | Create a new global address | bool | `"true"` | no |
93+
| create\_url\_map | Set to `false` if url_map variable is provided. | bool | `"true"` | no |
94+
| firewall\_networks | Names of the networks to create firewall rules in | list(string) | `<list>` | no |
95+
| firewall\_projects | Names of the projects to create firewall rules in | list(string) | `<list>` | no |
96+
| http\_forward | Set to `false` to disable HTTP port 80 forward | bool | `"true"` | no |
97+
| ip\_version | IP version for the Global address (IPv4 or v6) - Empty defaults to IPV4 | string | `"null"` | no |
98+
| name | Name for the forwarding rule and prefix for supporting resources | string | n/a | yes |
99+
| private\_key | Content of the private SSL key. Required if `ssl` is `true` and `ssl_certificates` is empty. | string | `"null"` | no |
100+
| project | The project to deploy to, if not set the default provider project is used. | string | n/a | yes |
101+
| quic | Set to `true` to enable QUIC support | bool | `"false"` | no |
102+
| security\_policy | The resource URL for the security policy to associate with the backend service | string | `"null"` | no |
103+
| ssl | Set to `true` to enable SSL support, requires variable `ssl_certificates` - a list of self_link certs | bool | `"false"` | no |
104+
| ssl\_certificates | SSL cert self_link list. Required if `ssl` is `true` and no `private_key` and `certificate` is provided. | list(string) | `<list>` | no |
105+
| ssl\_policy | Selfink to SSL Policy | string | `"null"` | no |
106+
| target\_tags | List of target tags for health check firewall rule. | list(string) | n/a | yes |
107+
| url\_map | The url_map resource to use. Default is to send all traffic to first backend. | string | `"null"` | no |
108+
| use\_ssl\_certificates | If true, use the certificates provided by `ssl_certificates`, otherwise, create cert from `private_key` and `certificate` | bool | `"false"` | no |
109+
110+
## Outputs
111+
112+
| Name | Description |
113+
|------|-------------|
114+
| backend\_services | The backend service resources. |
115+
| external\_ip | The external IP assigned to the global fowarding rule. |
116+
| http\_proxy | The HTTP proxy used by this module. |
117+
| https\_proxy | The HTTPS proxyused by this module. |
118+
119+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
120+
121+
- [`google_compute_global_forwarding_rule.http`](https://www.terraform.io/docs/providers/google/r/compute_global_forwarding_rule.html): The global HTTP forwarding rule.
122+
- [`google_compute_global_forwarding_rule.https`](https://www.terraform.io/docs/providers/google/r/compute_global_forwarding_rule.html): The global HTTPS forwarding rule created when `ssl` is `true`.
123+
- [`google_compute_target_http_proxy.default`](https://www.terraform.io/docs/providers/google/r/compute_target_http_proxy.html): The HTTP proxy resource that binds the url map. Created when input `ssl` is `false`.
124+
- [`google_compute_target_https_proxy.default`](https://www.terraform.io/docs/providers/google/r/compute_target_https_proxy.html): The HTTPS proxy resource that binds the url map. Created when input `ssl` is `true`.
125+
- [`google_compute_ssl_certificate.default`](https://www.terraform.io/docs/providers/google/r/compute_ssl_certificate.html): The certificate resource created when input `ssl` is `true`.
126+
- [`google_compute_url_map.default`](https://www.terraform.io/docs/providers/google/r/compute_url_map.html): The default URL map resource when input `url_map` is not provided.
127+
- [`google_compute_backend_service.default.*`](https://www.terraform.io/docs/providers/google/r/compute_backend_service.html): The backend services created for each of the `backend_params` elements.
128+
- [`google_compute_health_check.default.*`](https://www.terraform.io/docs/providers/google/r/compute_health_check.html): Health check resources create for each of the backend services.
129+
- [`google_compute_firewall.default-hc`](https://www.terraform.io/docs/providers/google/r/compute_firewall.html): Firewall rule created for each of the backed services to alllow health checks to the instance group.

autogen/main.tf.tmpl

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/**
2+
* Copyright 2017 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
18+
locals {
19+
address = var.create_address ? join("", google_compute_global_address.default.*.address) : var.address
20+
url_map = var.create_url_map ? join("", google_compute_url_map.default.*.self_link) : var.url_map
21+
}
22+
23+
resource "google_compute_global_forwarding_rule" "http" {
24+
project = var.project
25+
count = var.http_forward ? 1 : 0
26+
name = var.name
27+
target = google_compute_target_http_proxy.default[0].self_link
28+
ip_address = local.address
29+
port_range = "80"
30+
}
31+
32+
resource "google_compute_global_forwarding_rule" "https" {
33+
project = var.project
34+
count = var.ssl ? 1 : 0
35+
name = "${var.name}-https"
36+
target = google_compute_target_https_proxy.default[0].self_link
37+
ip_address = local.address
38+
port_range = "443"
39+
}
40+
41+
resource "google_compute_global_address" "default" {
42+
count = var.create_address ? 1 : 0
43+
project = var.project
44+
name = "${var.name}-address"
45+
ip_version = var.ip_version
46+
}
47+
48+
# HTTP proxy when http forwarding is true
49+
resource "google_compute_target_http_proxy" "default" {
50+
project = var.project
51+
count = var.http_forward ? 1 : 0
52+
name = "${var.name}-http-proxy"
53+
url_map = local.url_map
54+
}
55+
56+
# HTTPS proxy when ssl is true
57+
resource "google_compute_target_https_proxy" "default" {
58+
project = var.project
59+
count = var.ssl ? 1 : 0
60+
name = "${var.name}-https-proxy"
61+
url_map = local.url_map
62+
63+
ssl_certificates = compact(concat(var.ssl_certificates, google_compute_ssl_certificate.default.*.self_link, ), )
64+
ssl_policy = var.ssl_policy
65+
quic_override = var.quic ? "ENABLE" : null
66+
}
67+
68+
resource "google_compute_ssl_certificate" "default" {
69+
project = var.project
70+
count = var.ssl && ! var.use_ssl_certificates ? 1 : 0
71+
name_prefix = "${var.name}-certificate-"
72+
private_key = var.private_key
73+
certificate = var.certificate
74+
75+
lifecycle {
76+
create_before_destroy = true
77+
}
78+
}
79+
80+
resource "google_compute_url_map" "default" {
81+
project = var.project
82+
count = var.create_url_map ? 1 : 0
83+
name = "${var.name}-url-map"
84+
default_service = google_compute_backend_service.default[keys(var.backends)[0]].self_link
85+
86+
}
87+
88+
resource "google_compute_backend_service" "default" {
89+
for_each = var.backends
90+
91+
project = var.project
92+
name = "${var.name}-backend-${each.key}"
93+
94+
port_name = each.value.port_name
95+
protocol = each.value.protocol
96+
timeout_sec = lookup(each.value, "timeout_sec", null)
97+
description = lookup(each.value, "description", null)
98+
connection_draining_timeout_sec = lookup(each.value, "connection_draining_timeout_sec", null)
99+
enable_cdn = lookup(each.value, "enable_cdn", false)
100+
security_policy = var.security_policy
101+
health_checks = [google_compute_health_check.default[each.key].self_link]
102+
103+
dynamic "backend" {
104+
for_each = toset(each.value["groups"])
105+
content {
106+
balancing_mode = lookup(backend.value, "balancing_mode")
107+
capacity_scaler = lookup(backend.value, "capacity_scaler")
108+
description = lookup(backend.value, "description")
109+
group = lookup(backend.value, "group")
110+
max_connections = lookup(backend.value, "max_connections")
111+
max_connections_per_instance = lookup(backend.value, "max_connections_per_instance")
112+
max_connections_per_endpoint = lookup(backend.value, "max_connections_per_endpoint")
113+
max_rate = lookup(backend.value, "max_rate")
114+
max_rate_per_instance = lookup(backend.value, "max_rate_per_instance")
115+
max_rate_per_endpoint = lookup(backend.value, "max_rate_per_endpoint")
116+
max_utilization = lookup(backend.value, "max_utilization")
117+
}
118+
}
119+
120+
depends_on = [google_compute_health_check.default]
121+
122+
{% if dynamic_backends %}
123+
lifecycle {
124+
ignore_changes = [backend]
125+
}
126+
{% endif %}
127+
}
128+
129+
resource "google_compute_health_check" "default" {
130+
for_each = var.backends
131+
project = var.project
132+
name = "${var.name}-hc-${each.key}"
133+
134+
check_interval_sec = lookup(each.value["health_check"], "check_interval_sec", 5)
135+
timeout_sec = lookup(each.value["health_check"], "timeout_sec", 5)
136+
healthy_threshold = lookup(each.value["health_check"], "healthy_threshold", 2)
137+
unhealthy_threshold = lookup(each.value["health_check"], "unhealthy_threshold", 2)
138+
139+
dynamic "http_health_check" {
140+
for_each = each.value["protocol"] == "HTTP" ? [
141+
{
142+
host = lookup(each.value["health_check"], "host", null)
143+
request_path = lookup(each.value["health_check"], "request_path", null)
144+
port = lookup(each.value["health_check"], "port", null)
145+
}
146+
] : []
147+
148+
content {
149+
host = lookup(http_health_check.value, "host", null)
150+
request_path = lookup(http_health_check.value, "request_path", null)
151+
port = lookup(http_health_check.value, "port", null)
152+
}
153+
}
154+
155+
dynamic "https_health_check" {
156+
for_each = each.value["protocol"] == "HTTPS" ? [
157+
{
158+
host = lookup(each.value["health_check"], "host", null)
159+
request_path = lookup(each.value["health_check"], "request_path", null)
160+
port = lookup(each.value["health_check"], "port", null)
161+
}
162+
] : []
163+
164+
content {
165+
host = lookup(https_health_check.value, "host", null)
166+
request_path = lookup(https_health_check.value, "request_path", null)
167+
port = lookup(https_health_check.value, "port", null)
168+
}
169+
}
170+
171+
dynamic "http2_health_check" {
172+
for_each = each.value["protocol"] == "HTTP2" ? [
173+
{
174+
host = lookup(each.value["health_check"], "host", null)
175+
request_path = lookup(each.value["health_check"], "request_path", null)
176+
port = lookup(each.value["health_check"], "port", null)
177+
}
178+
] : []
179+
180+
content {
181+
host = lookup(http2_health_check.value, "host", null)
182+
request_path = lookup(http2_health_check.value, "request_path", null)
183+
port = lookup(http2_health_check.value, "port", null)
184+
}
185+
}
186+
187+
}
188+
189+
resource "google_compute_firewall" "default-hc" {
190+
count = length(var.firewall_networks)
191+
project = length(var.firewall_networks) == 1 && var.firewall_projects[0] == "default" ? var.project : var.firewall_projects[count.index]
192+
name = "${var.name}-hc-${count.index}"
193+
network = var.firewall_networks[count.index]
194+
source_ranges = [
195+
"130.211.0.0/22",
196+
"35.191.0.0/16"
197+
]
198+
target_tags = var.target_tags
199+
200+
dynamic "allow" {
201+
for_each = var.backends
202+
content {
203+
protocol = "tcp"
204+
ports = [allow.value.port]
205+
}
206+
}
207+
}

0 commit comments

Comments
 (0)