diff --git a/modules/compute-mig/main.tf b/modules/compute-mig/main.tf index 85c25b86..4328b018 100644 --- a/modules/compute-mig/main.tf +++ b/modules/compute-mig/main.tf @@ -257,9 +257,9 @@ resource "google_compute_region_instance_group_manager" "default" { } } -resource "google_compute_health_check" "default" { +resource "google_compute_health_check" "http" { provider = google-beta - count = var.health_check_config == null ? 0 : 1 + count = try(var.health_check_config.type, null) == "http" ? 1 : 0 project = var.project_id name = var.name description = "Terraform managed." @@ -269,92 +269,132 @@ resource "google_compute_health_check" "default" { timeout_sec = try(var.health_check_config.config.timeout_sec, null) unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null) - dynamic http_health_check { - for_each = ( - try(var.health_check_config.type, null) == "http" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - host = try(check.value.host, null) - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request_path = try(check.value.request_path, null) - response = try(check.value.response, null) - } - } - - dynamic https_health_check { - for_each = ( - try(var.health_check_config.type, null) == "https" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - host = try(check.value.host, null) - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request_path = try(check.value.request_path, null) - response = try(check.value.response, null) - } - } - - dynamic tcp_health_check { - for_each = ( - try(var.health_check_config.type, null) == "tcp" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request = try(check.value.request, null) - response = try(check.value.response, null) - } - } - - dynamic ssl_health_check { - for_each = ( - try(var.health_check_config.type, null) == "ssl" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request = try(check.value.request, null) - response = try(check.value.response, null) - } - } - - dynamic http2_health_check { - for_each = ( - try(var.health_check_config.type, null) == "http2" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - host = try(check.value.host, null) - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request_path = try(check.value.request_path, null) - response = try(check.value.response, 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) ? [""] : [] + content { + enable = true + } + } +} + +resource "google_compute_health_check" "https" { + provider = google-beta + count = try(var.health_check_config.type, null) == "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) ? [""] : [] + content { + enable = true + } + } +} + +resource "google_compute_health_check" "tcp" { + provider = google-beta + count = try(var.health_check_config.type, null) == "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 = try(var.health_check_config.type, null) == "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 = try(var.health_check_config.type, null) == "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 { @@ -363,5 +403,4 @@ resource "google_compute_health_check" "default" { enable = true } } - } diff --git a/modules/compute-mig/outputs.tf b/modules/compute-mig/outputs.tf index ca038a22..649cb603 100644 --- a/modules/compute-mig/outputs.tf +++ b/modules/compute-mig/outputs.tf @@ -34,7 +34,16 @@ output "group_manager" { output "health_check" { description = "Auto-created health-check resource." - value = var.health_check_config == null ? null : try( - google_compute_health_check.default.0, {} + value = ( + var.health_check_config == null + ? null + : 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, + {} + ) ) } diff --git a/modules/compute-mig/variables.tf b/modules/compute-mig/variables.tf index 925ef7b7..2578269a 100644 --- a/modules/compute-mig/variables.tf +++ b/modules/compute-mig/variables.tf @@ -51,7 +51,7 @@ variable "default_version" { } variable "health_check_config" { - description = "Optional auto-created helth check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage." + 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 diff --git a/modules/net-ilb/main.tf b/modules/net-ilb/main.tf index d271402f..eb6ee475 100644 --- a/modules/net-ilb/main.tf +++ b/modules/net-ilb/main.tf @@ -17,9 +17,17 @@ locals { health_check = ( - var.health_check == null - ? try(google_compute_health_check.default.0.self_link, null) - : var.health_check + var.health_check != null + ? var.health_check + : try(local.health_check_resource.self_link, null) + ) + 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, + {} ) } @@ -81,9 +89,9 @@ resource "google_compute_region_backend_service" "default" { } -resource "google_compute_health_check" "default" { +resource "google_compute_health_check" "http" { provider = google-beta - count = var.health_check == null ? 1 : 0 + count = try(var.health_check_config.type, null) == "http" ? 1 : 0 project = var.project_id name = var.name description = "Terraform managed." @@ -93,92 +101,14 @@ resource "google_compute_health_check" "default" { timeout_sec = try(var.health_check_config.config.timeout_sec, null) unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null) - dynamic http_health_check { - for_each = ( - try(var.health_check_config.type, null) == "http" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - host = try(check.value.host, null) - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request_path = try(check.value.request_path, null) - response = try(check.value.response, null) - } - } - - dynamic https_health_check { - for_each = ( - try(var.health_check_config.type, null) == "https" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - host = try(check.value.host, null) - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request_path = try(check.value.request_path, null) - response = try(check.value.response, null) - } - } - - dynamic tcp_health_check { - for_each = ( - try(var.health_check_config.type, null) == "tcp" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request = try(check.value.request, null) - response = try(check.value.response, null) - } - } - - dynamic ssl_health_check { - for_each = ( - try(var.health_check_config.type, null) == "ssl" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request = try(check.value.request, null) - response = try(check.value.response, null) - } - } - - dynamic http2_health_check { - for_each = ( - try(var.health_check_config.type, null) == "http2" - ? [var.health_check_config.check] - : [] - ) - iterator = check - content { - host = try(check.value.host, null) - port = try(check.value.port, null) - port_name = try(check.value.port_name, null) - port_specification = try(check.value.port_specification, null) - proxy_header = try(check.value.proxy_header, null) - request_path = try(check.value.request_path, null) - response = try(check.value.response, 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 { @@ -187,5 +117,123 @@ resource "google_compute_health_check" "default" { enable = true } } - } + +resource "google_compute_health_check" "https" { + provider = google-beta + count = try(var.health_check_config.type, null) == "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) ? [""] : [] + content { + enable = true + } + } +} + +resource "google_compute_health_check" "tcp" { + provider = google-beta + count = try(var.health_check_config.type, null) == "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 = try(var.health_check_config.type, null) == "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 = try(var.health_check_config.type, null) == "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 a3529eba..8418e40a 100644 --- a/modules/net-ilb/outputs.tf +++ b/modules/net-ilb/outputs.tf @@ -51,15 +51,15 @@ output "forwarding_rule_self_link" { output "health_check" { description = "Auto-created health-check resource." - value = try(google_compute_health_check.default.0, {}) + value = local.health_check_resource } output "health_check_self_id" { description = "Auto-created health-check self id." - value = try(google_compute_health_check.default.0.id, null) + value = try(local.health_check_resource.id, null) } output "health_check_self_link" { description = "Auto-created health-check self link." - value = try(google_compute_health_check.default.0.self_link, null) + value = try(local.health_check_resource.self_link, null) } diff --git a/tests/modules/compute_mig/__init__.py b/tests/modules/compute_mig/__init__.py new file mode 100644 index 00000000..6913f02e --- /dev/null +++ b/tests/modules/compute_mig/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020 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. diff --git a/tests/modules/compute_mig/fixture/main.tf b/tests/modules/compute_mig/fixture/main.tf new file mode 100644 index 00000000..3addb026 --- /dev/null +++ b/tests/modules/compute_mig/fixture/main.tf @@ -0,0 +1,33 @@ +/** + * Copyright 2020 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. + */ + +module "test" { + source = "../../../../modules/compute-mig" + project_id = "my-project" + location = "europe-west1" + name = "test-mig" + target_size = 2 + default_version = { + instance_template = "foo-template" + name = "foo" + } + autoscaler_config = var.autoscaler_config + health_check_config = var.health_check_config + named_ports = var.named_ports + regional = var.regional + update_policy = var.update_policy + versions = var.versions +} diff --git a/tests/modules/compute_mig/fixture/variables.tf b/tests/modules/compute_mig/fixture/variables.tf new file mode 100644 index 00000000..fa0ac9da --- /dev/null +++ b/tests/modules/compute_mig/fixture/variables.tf @@ -0,0 +1,83 @@ +/** + * Copyright 2020 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. + */ + +variable "autoscaler_config" { + type = object({ + max_replicas = number + min_replicas = number + cooldown_period = number + cpu_utilization_target = number + load_balancing_utilization_target = number + metric = object({ + name = string + single_instance_assignment = number + target = number + type = string # GAUGE, DELTA_PER_SECOND, DELTA_PER_MINUTE + filter = string + }) + }) + default = null +} + +variable "auto_healing_policies" { + type = object({ + health_check = string + initial_delay_sec = number + }) + 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 = null +} + +variable "named_ports" { + type = map(number) + default = null +} + +variable "regional" { + type = bool + default = false +} + +variable "update_policy" { + type = object({ + type = string # OPPORTUNISTIC | PROACTIVE + minimal_action = string # REPLACE | RESTART + min_ready_sec = number + max_surge_type = string # fixed | percent + max_surge = number + max_unavailable_type = string + max_unavailable = number + }) + default = null +} + +variable "versions" { + type = map(object({ + instance_template = string + target_type = string # fixed | percent + target_size = number + })) + default = null +} diff --git a/tests/modules/compute_mig/test_plan.py b/tests/modules/compute_mig/test_plan.py new file mode 100644 index 00000000..c581750e --- /dev/null +++ b/tests/modules/compute_mig/test_plan.py @@ -0,0 +1,73 @@ +# Copyright 2020 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. + + +import os +import pytest + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') + + +def test_defaults(plan_runner): + "Test variable defaults." + _, resources = plan_runner(FIXTURES_DIR) + assert len(resources) == 1 + mig = resources[0] + assert mig['type'] == 'google_compute_instance_group_manager' + assert mig['values']['target_size'] == 2 + assert mig['values']['zone'] + _, resources = plan_runner(FIXTURES_DIR, regional='true') + assert len(resources) == 1 + mig = resources[0] + assert mig['type'] == 'google_compute_region_instance_group_manager' + assert mig['values']['target_size'] == 2 + assert mig['values']['region'] + + +def test_health_check(plan_runner): + "Test health check resource." + health_check_config = '{type="tcp", check={port=80}, config=null, logging=false}' + _, resources = plan_runner( + FIXTURES_DIR, health_check_config=health_check_config) + assert len(resources) == 2 + assert any(r['type'] == 'google_compute_health_check' for r in resources) + + +def test_autoscaler(plan_runner): + "Test autoscaler resource." + autoscaler_config = ( + '{' + 'max_replicas=3, min_replicas=1, cooldown_period=60,' + 'cpu_utilization_target=65, load_balancing_utilization_target=null,' + 'metric=null' + '}' + ) + _, resources = plan_runner(FIXTURES_DIR, autoscaler_config=autoscaler_config) + assert len(resources) == 2 + autoscaler = resources[0] + assert autoscaler['type'] == 'google_compute_autoscaler' + assert autoscaler['values']['autoscaling_policy'] == [{ + 'cooldown_period': 60, + 'cpu_utilization': [{'target': 65}], + 'load_balancing_utilization': [], + 'max_replicas': 3, + 'metric': [], + 'min_replicas': 1 + }] + _, resources = plan_runner( + FIXTURES_DIR, autoscaler_config=autoscaler_config, regional='true') + assert len(resources) == 2 + autoscaler = resources[0] + assert autoscaler['type'] == 'google_compute_region_autoscaler'