FAQ | This is a LIVE service | Changelog

Skip to content
Commits on Source (5)
......@@ -58,9 +58,10 @@ tests:
tags:
- $GKE_RUNNER_TAG
parallel:
# This matrix runs each of our test files in parallel targeting v4.x and v5.x of the Google Terraform provider
# separately as we support both. It also ensures that subnet CIDR ranges do not clash when testing the VPC
# Access/static egress IP configurations.
# This matrix can run each of our test files in parallel targeting different versions of the
# Google Terraform provider separately (although we currently only support >=6 due to
# dependency constraints). It also ensures that subnet CIDR ranges do not clash when testing
# the VPC Access/static egress IP configurations.
matrix:
- TEST_FILE:
- cloud_run_service.tftest.hcl
......@@ -68,26 +69,25 @@ tests:
- load_balancer.tftest.hcl
- pre_deploy_job.tftest.hcl
GOOGLE_PROVIDER_VERSION_CONSTRAINT:
- "> 4, < 5"
- "> 5, < 6"
- ">= 6"
- TEST_FILE:
- monitoring.tftest.hcl
GOOGLE_PROVIDER_VERSION_CONSTRAINT: "> 4, < 5"
GOOGLE_PROVIDER_VERSION_CONSTRAINT: ">= 6"
TF_VAR_static_egress_ip_cidr_range: "10.0.0.0/28"
TF_VAR_test_ip_cidr_range: "10.0.0.16/28"
- TEST_FILE:
- monitoring.tftest.hcl
GOOGLE_PROVIDER_VERSION_CONSTRAINT: "> 5, < 6"
GOOGLE_PROVIDER_VERSION_CONSTRAINT: ">= 6"
TF_VAR_static_egress_ip_cidr_range: "10.0.0.32/28"
TF_VAR_test_ip_cidr_range: "10.0.0.48/28"
- TEST_FILE:
- vpc_access.tftest.hcl
GOOGLE_PROVIDER_VERSION_CONSTRAINT: "> 4, < 5"
GOOGLE_PROVIDER_VERSION_CONSTRAINT: ">= 6"
TF_VAR_static_egress_ip_cidr_range: "10.0.0.64/28"
TF_VAR_test_ip_cidr_range: "10.0.0.80/28"
- TEST_FILE:
- vpc_access.tftest.hcl
GOOGLE_PROVIDER_VERSION_CONSTRAINT: "> 5, < 6"
GOOGLE_PROVIDER_VERSION_CONSTRAINT: ">= 6"
TF_VAR_static_egress_ip_cidr_range: "10.0.0.96/28"
TF_VAR_test_ip_cidr_range: "10.0.0.112/28"
......
# Changelog
## [10.0.0](https://gitlab.developers.cam.ac.uk/uis/devops/infra/terraform/gcp-cloud-run-app/compare/9.2.0...10.0.0) (2024-11-18)
### ⚠ BREAKING CHANGES
* **deps:** Remove the `use_ssl_certificates` variable as the load
balancer module no longer accepts it.
Update tests and examples to use a more recent version (v23) of the SQL
module to resolve provider version conflicts.
Modify tests to only verify Google provider versions >= 6 as this is the
minimum version supported by Google's load balancer module.
### Bug Fixes
* tests after provider version upgrade ([872333d](https://gitlab.developers.cam.ac.uk/uis/devops/infra/terraform/gcp-cloud-run-app/commit/872333dcf538b3de01ad812e5e7f9b190597829a))
### Miscellaneous Chores
* **deps:** update terraform googlecloudplatform/lb-http/google to v12 ([f315654](https://gitlab.developers.cam.ac.uk/uis/devops/infra/terraform/gcp-cloud-run-app/commit/f315654173129805698b40af0191b01c0665fbe7))
## [9.2.0](https://gitlab.developers.cam.ac.uk/uis/devops/infra/terraform/gcp-cloud-run-app/compare/9.1.2...9.2.0) (2024-10-01)
......
......@@ -59,6 +59,7 @@ For more information on how the pre-deploy Cloud Run job works see the
| <a name="input_allow_unauthenticated_invocations"></a> [allow\_unauthenticated\_invocations](#input\_allow\_unauthenticated\_invocations) | If true, the webapp will allow unauthenticated invocations. If false, the<br>webapp requires authentication as a Google user with the Cloud Run invoker<br>permission on the deployment. | `bool` | `true` | no |
| <a name="input_containers"></a> [containers](#input\_containers) | Configure one or more container instances for the service. See<br>https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_service#nested_containers<br>for information on the available arguments. | <pre>map(object({<br> name = optional(string)<br> image = string<br> command = optional(list(string))<br> args = optional(list(string))<br> env = optional(list(object({<br> name = string<br> value = optional(string)<br> value_source = optional(object({<br> secret_key_ref = optional(object({<br> secret = string<br> version = optional(string, "latest")<br> }))<br> }))<br> })), [])<br> resources = optional(object({<br> limits = optional(map(string))<br> cpu_idle = optional(bool, true)<br> startup_cpu_boost = optional(bool, true)<br> }))<br> ports = optional(list(object({<br> name = optional(string)<br> container_port = optional(number)<br> })), [])<br> volume_mounts = optional(list(object({<br> name = string<br> mount_path = string<br> })), [])<br> working_dir = optional(string)<br> liveness_probe = optional(object({<br> initial_delay_seconds = optional(number)<br> timeout_seconds = optional(number)<br> period_seconds = optional(number)<br> failure_threshold = optional(number)<br> http_get = optional(object({<br> path = optional(string)<br> port = optional(number)<br> http_headers = optional(list(object({<br> name = string<br> value = optional(string)<br> })), [])<br> }))<br> grpc = optional(object({<br> port = optional(number)<br> service = optional(string)<br> }))<br> }))<br> startup_probe = optional(object({<br> initial_delay_seconds = optional(number)<br> timeout_seconds = optional(number)<br> period_seconds = optional(number)<br> failure_threshold = optional(number)<br> http_get = optional(object({<br> path = optional(string)<br> port = optional(number)<br> http_headers = optional(list(object({<br> name = string<br> value = optional(string)<br> })), [])<br> }))<br> tcp_socket = optional(object({<br> port = number<br> }))<br> grpc = optional(object({<br> port = optional(number)<br> service = optional(string)<br> }))<br> }))<br> }))</pre> | n/a | yes |
| <a name="input_create_ipv6_address"></a> [create\_ipv6\_address](#input\_create\_ipv6\_address) | Allocate an IPv6 address to the load balancer if var.enable\_ipv6 is true. | `bool` | `false` | no |
| <a name="input_deletion_protection"></a> [deletion\_protection](#input\_deletion\_protection) | Optional. Whether Terraform will be prevented from destroying<br>the Cloud Run resource. Defaults to false. | `bool` | `false` | no |
| <a name="input_description"></a> [description](#input\_description) | A description for the Cloud Run service. | `string` | `null` | no |
| <a name="input_dns_names"></a> [dns\_names](#input\_dns\_names) | DNS names to configure for the web application. Note that DNS records are<br>\_NOT\_ created, they are used in the load balancer module to ensure the SSL<br>certificate is generated with the required SANs. The map's keys are arbitrary<br>and are only required to avoid errors when the DNS name is a value which<br>Terraform does not know until after the apply operation.<br><br>For example:<br><br>{ my\_awesome\_dns\_name = "awesome.example.com" } | `map(string)` | `{}` | no |
| <a name="input_enable_alerting"></a> [enable\_alerting](#input\_enable\_alerting) | Enable alerting policies. | `bool` | `true` | no |
......@@ -112,10 +113,10 @@ For more information on how the pre-deploy Cloud Run job works see the
| <a name="input_template_labels"></a> [template\_labels](#input\_template\_labels) | A set of key/value label pairs to assign to the Cloud Run service revision. | `map(string)` | `{}` | no |
| <a name="input_timeout_seconds"></a> [timeout\_seconds](#input\_timeout\_seconds) | The maximum duration, in seconds, the instance is allowed for responding to a<br>request. Maximum is 900s. | `string` | `"300s"` | no |
| <a name="input_traffic"></a> [traffic](#input\_traffic) | Configure traffic allocation between one or more service revisions. | <pre>list(object({<br> type = optional(string)<br> revision = optional(string)<br> percent = optional(number)<br> tag = optional(string)<br> }))</pre> | `[]` | no |
| <a name="input_use_ssl_certificates"></a> [use\_ssl\_certificates](#input\_use\_ssl\_certificates) | Whether to use the custom TLS certs in var.ssl\_certificates for the load<br>balancer or the Google-managed certs for the specified var.dns\_names. | `bool` | `false` | no |
| <a name="input_volumes"></a> [volumes](#input\_volumes) | Configure one or more volumes for the service. See<br>https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_service#nested_volumes<br>for more information on these options. | <pre>list(object({<br> name = string<br> secret = optional(object({<br> secret = string<br> default_mode = optional(number)<br> items = optional(list(object({<br> path = string<br> version = optional(string)<br> mode = optional(number)<br> })), [])<br> }))<br> cloud_sql_instance = optional(object({<br> instances = optional(list(string))<br> }))<br> }))</pre> | `[]` | no |
| <a name="input_vpc_access"></a> [vpc\_access](#input\_vpc\_access) | Configure VPC access for the Cloud Run service. For more information on these<br>options see<br>https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_service#nested_vpc_access | <pre>object({<br> connector = optional(string)<br> egress = optional(string)<br> network_interfaces = optional(object({<br> network = optional(string)<br> subnetwork = optional(string)<br> tags = optional(string)<br> }))<br> })</pre> | `null` | no |
| <a name="input_vpc_access_connector_max_throughput"></a> [vpc\_access\_connector\_max\_throughput](#input\_vpc\_access\_connector\_max\_throughput) | Optional. The maximum throughput of the connector in megabytes per second.<br>Defaults to 300. | `number` | `300` | no |
| <a name="input_vpc_access_connector_min_throughput"></a> [vpc\_access\_connector\_min\_throughput](#input\_vpc\_access\_connector\_min\_throughput) | Optional. The minimum throughput of the connector in megabytes per second.<br>Defaults to 200. | `number` | `200` | no |
## Outputs
......
......@@ -161,7 +161,7 @@ module "webapp" {
module "sql" {
source = "GoogleCloudPlatform/sql-db/google//modules/postgresql"
version = "~> 17.0"
version = "~> 23.0"
database_version = "POSTGRES_15"
name = "test-sql-1234"
......@@ -210,7 +210,7 @@ module "webapp" {
module "sql" {
source = "GoogleCloudPlatform/sql-db/google//modules/postgresql"
version = "~> 17.0"
version = "~> 23.0"
database_version = "POSTGRES_15"
name = "test-sql-1234"
......
......@@ -32,7 +32,7 @@ module "webapp_http_load_balancer" {
# The double slash is important(!)
source = "GoogleCloudPlatform/lb-http/google//modules/serverless_negs"
version = "~> 9.0"
version = "~> 12.0"
project = var.project
name = var.name
......@@ -42,9 +42,8 @@ module "webapp_http_load_balancer" {
ssl_policy = var.ssl_policy == null ? google_compute_ssl_policy.default[0].id : var.ssl_policy
https_redirect = true
# Use custom TLS certs if var.use_ssl_certificates is true, otherwise, use the Google-managed certs.
use_ssl_certificates = var.use_ssl_certificates
ssl_certificates = var.ssl_certificates
# Specify custom TLS certs, otherwise the Google-managed certs will be used.
ssl_certificates = var.ssl_certificates
# Whether to create an IPv6 address to the load balancer.
enable_ipv6 = var.enable_ipv6
......
......@@ -21,15 +21,16 @@ resource "google_project_iam_member" "webapp_sql_client" {
}
resource "google_cloud_run_v2_service" "webapp" {
name = var.name
location = var.region
description = var.description
project = var.project
labels = var.service_labels
client = "terraform"
ingress = local.ingress
launch_stage = var.launch_stage
annotations = var.service_annotations
name = var.name
location = var.region
description = var.description
project = var.project
labels = var.service_labels
client = "terraform"
ingress = local.ingress
launch_stage = var.launch_stage
annotations = var.service_annotations
deletion_protection = var.deletion_protection
template {
revision = var.revision
......@@ -304,10 +305,11 @@ module "uptime_monitoring" {
resource "google_cloud_run_v2_job" "pre_deploy" {
count = var.enable_pre_deploy_job ? 1 : 0
name = "${var.name}-pre-deploy"
location = var.region
project = var.project
launch_stage = var.pre_deploy_job_launch_stage
name = "${var.name}-pre-deploy"
location = var.region
project = var.project
launch_stage = var.pre_deploy_job_launch_stage
deletion_protection = var.deletion_protection
template {
labels = var.pre_deploy_job_labels
......
......@@ -22,6 +22,7 @@ resource "google_vpc_access_connector" "main" {
project = var.project
region = var.region
max_throughput = var.vpc_access_connector_max_throughput
min_throughput = var.vpc_access_connector_min_throughput
subnet {
name = google_compute_subnetwork.vpc_connector[0].name
......
......@@ -174,19 +174,31 @@ run "test_env_vars_and_secrets" {
}
assert {
condition = google_cloud_run_v2_service.webapp.template[0].containers[0].env[0].name == "HELLO"
condition = length([
for env_var in google_cloud_run_v2_service.webapp.template[0].containers[0].env :
env_var.name if env_var.name == "HELLO"
]) > 0
error_message = "A standard environment variable with the name 'HELLO' should be created."
}
assert {
condition = google_cloud_run_v2_service.webapp.template[0].containers[0].env[0].value == "WORLD!"
error_message = "A standard environment variable with the value 'WORLD!' should be created."
condition = length([
for env_var in google_cloud_run_v2_service.webapp.template[0].containers[0].env :
env_var.value if env_var.value == "WORLD!"
]) > 0
error_message = "A standard environment variable with the name 'WORLD!' should be created."
}
assert {
condition = google_cloud_run_v2_service.webapp.template[0].containers[0].env[1].name == "SECRET"
condition = length([
for env_var in google_cloud_run_v2_service.webapp.template[0].containers[0].env :
env_var.name if env_var.name == "SECRET"
]) > 0
error_message = "A secret-backed environment variable with the name 'SECRET' should be created."
}
assert {
condition = google_cloud_run_v2_service.webapp.template[0].containers[0].env[1].value_source[0].secret_key_ref[0].secret == run.setup.secret_ids[0]
condition = [
for env_var in google_cloud_run_v2_service.webapp.template[0].containers[0].env :
env_var.value_source if length(env_var.value_source) > 0
][0][0].secret_key_ref[0].secret == run.setup.secret_ids[0]
error_message = "A secret-backed environment variable referencing the 'run.setup.secret_ids[0]' secret should be created."
}
assert {
......
......@@ -87,19 +87,31 @@ run "test_pre_deploy_job_env_vars_and_secrets" {
}
assert {
condition = google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env[0].name == "HELLO"
condition = length([
for env_var in google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env :
env_var.name if env_var.name == "HELLO"
]) > 0
error_message = "A standard environment variable with the name 'HELLO' should be created."
}
assert {
condition = google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env[0].value == "WORLD!"
error_message = "A standard environment variable with the value 'WORLD!' should be created."
condition = length([
for env_var in google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env :
env_var.value if env_var.value == "WORLD!"
]) > 0
error_message = "A standard environment variable with the name 'WORLD!' should be created."
}
assert {
condition = google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env[1].name == "SECRET"
condition = length([
for env_var in google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env :
env_var.name if env_var.name == "SECRET"
]) > 0
error_message = "A secret-backed environment variable with the name 'SECRET' should be created."
}
assert {
condition = google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env[1].value_source[0].secret_key_ref[0].secret == run.setup.secret_ids[0]
condition = [
for env_var in google_cloud_run_v2_job.pre_deploy[0].template[0].template[0].containers[0].env :
env_var.value_source if length(env_var.value_source) > 0
][0][0].secret_key_ref[0].secret == run.setup.secret_ids[0]
error_message = "A secret-backed environment variable referencing the 'run.setup.secret_ids[0]' secret should be created."
}
assert {
......
......@@ -14,7 +14,7 @@ module "sql" {
count = var.create_test_sql_instances ? 2 : 0
source = "GoogleCloudPlatform/sql-db/google//modules/postgresql"
version = "~> 17.0"
version = "~> 23.0"
database_version = "POSTGRES_15"
name = "${random_id.name.hex}-${count.index}"
project_id = var.project
......@@ -66,6 +66,9 @@ resource "google_compute_subnetwork" "test" {
resource "google_vpc_access_connector" "test" {
count = var.create_vpc_connector ? 1 : 0
min_throughput = 200
max_throughput = 300
name = "${random_id.name.hex}-setup"
project = var.project
region = var.region
......
......@@ -348,16 +348,6 @@ For example:
EOI
}
variable "use_ssl_certificates" {
type = bool
default = false
description = <<EOI
Whether to use the custom TLS certs in var.ssl_certificates for the load
balancer or the Google-managed certs for the specified var.dns_names.
EOI
}
variable "ssl_certificates" {
type = list(any)
default = []
......@@ -726,6 +716,15 @@ Defaults to 300.
EOI
}
variable "vpc_access_connector_min_throughput" {
type = number
default = 200
description = <<EOI
Optional. The minimum throughput of the connector in megabytes per second.
Defaults to 200.
EOI
}
variable "load_balancer_backend" {
type = object({
port_name = optional(string)
......@@ -797,3 +796,12 @@ Optional. Custom options for the backend load balancer.
Defaults to {}.
EOI
}
variable "deletion_protection" {
default = false
type = bool
description = <<EOI
Optional. Whether Terraform will be prevented from destroying
the Cloud Run resource. Defaults to false.
EOI
}