From 9ecf78d290ad3098fa5a9e51178440ddbdbef03d Mon Sep 17 00:00:00 2001 From: CFT Bot Date: Thu, 13 Mar 2025 23:14:54 -0500 Subject: [PATCH 01/17] chore: update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index e2d75959..8429723e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,7 +1,7 @@ # NOTE: This file is automatically generated from values at: # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf -* @terraform-google-modules/cft-admins @imrannayer @isaurabhuttam @q2w +* @terraform-google-modules/cft-admins @ayushmjain @imrannayer @isaurabhuttam @q2w # NOTE: GitHub CODEOWNERS locations: # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-and-branch-protection From 4373bdb515930c1c544798f7490b35d709ce5292 Mon Sep 17 00:00:00 2001 From: Sven Schliesing Date: Mon, 17 Mar 2025 23:01:48 +0100 Subject: [PATCH 02/17] chore(docs): Fix description of "zone" (#710) Co-authored-by: Imran Nayer --- modules/safer_mysql/README.md | 2 +- modules/safer_mysql/metadata.yaml | 2 +- modules/safer_mysql/variables.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/safer_mysql/README.md b/modules/safer_mysql/README.md index 26b9d095..0fb9b364 100644 --- a/modules/safer_mysql/README.md +++ b/modules/safer_mysql/README.md @@ -288,7 +288,7 @@ module "safer-mysql-db" { | user\_name | The name of the default user | `string` | `"default"` | no | | user\_password | The password for the default user. If not set, a random one will be generated and available in the generated\_user\_password output variable. | `string` | `""` | no | | vpc\_network | Existing VPC network to which instances are connected. The networks needs to be configured with https://cloud.google.com/vpc/docs/configure-private-services-access. | `string` | n/a | yes | -| zone | The zone for the master instance, it should be something like: `a`, `c`. | `string` | `null` | no | +| zone | The zone for the master instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | ## Outputs diff --git a/modules/safer_mysql/metadata.yaml b/modules/safer_mysql/metadata.yaml index ee2a4318..f5494ae8 100644 --- a/modules/safer_mysql/metadata.yaml +++ b/modules/safer_mysql/metadata.yaml @@ -323,7 +323,7 @@ spec: varType: string required: true - name: zone - description: "The zone for the master instance, it should be something like: `a`, `c`." + description: "The zone for the master instance, it should be something like: `us-central1-a`, `us-east1-c`." varType: string outputs: - name: generated_user_password diff --git a/modules/safer_mysql/variables.tf b/modules/safer_mysql/variables.tf index c31e7889..3cf1f886 100644 --- a/modules/safer_mysql/variables.tf +++ b/modules/safer_mysql/variables.tf @@ -74,7 +74,7 @@ variable "edition" { } variable "zone" { - description = "The zone for the master instance, it should be something like: `a`, `c`." + description = "The zone for the master instance, it should be something like: `us-central1-a`, `us-east1-c`." type = string default = null } From db53c267bbba6f45d2c7f027b05d46e17f286a0c Mon Sep 17 00:00:00 2001 From: ps-occrp Date: Wed, 26 Mar 2025 21:55:41 +0100 Subject: [PATCH 03/17] feat: Add support for autokey in postgres module (#712) Co-authored-by: Imran Nayer --- examples/postgresql-ha/README.md | 2 + examples/postgresql-ha/main.tf | 13 ++++++ examples/postgresql-ha/outputs.tf | 6 ++- examples/postgresql-ha/variables.tf | 10 +++++ modules/postgresql/README.md | 1 + modules/postgresql/main.tf | 13 +++++- modules/postgresql/variables.tf | 6 +++ test/fixtures/postgresql-ha/main.tf | 5 +-- test/fixtures/postgresql-ha/variables.tf | 10 +++++ test/setup/iam.tf | 10 +++++ test/setup/main.tf | 57 +++++++++++++++++++++++- test/setup/outputs.tf | 8 ++++ 12 files changed, 133 insertions(+), 8 deletions(-) diff --git a/examples/postgresql-ha/README.md b/examples/postgresql-ha/README.md index 1e440507..0ee2835b 100644 --- a/examples/postgresql-ha/README.md +++ b/examples/postgresql-ha/README.md @@ -23,6 +23,8 @@ terraform destroy | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| folder\_id | The folder where project is created | `string` | n/a | yes | +| key\_project\_id | The project where autokey is setup | `string` | n/a | yes | | pg\_ha\_external\_ip\_range | The ip range to allow connecting from/to Cloud SQL | `string` | `"192.10.10.10/32"` | no | | pg\_ha\_name | The name for Cloud SQL instance | `string` | `"tf-pg-ha"` | no | | project\_id | The project to run tests against | `string` | n/a | yes | diff --git a/examples/postgresql-ha/main.tf b/examples/postgresql-ha/main.tf index 3fbcc667..8417f58b 100644 --- a/examples/postgresql-ha/main.tf +++ b/examples/postgresql-ha/main.tf @@ -48,6 +48,7 @@ module "pg" { maintenance_window_hour = 12 maintenance_window_update_track = "stable" + use_autokey = true deletion_protection = false database_flags = [{ name = "autovacuum", value = "off" }] @@ -127,4 +128,16 @@ module "pg" { random_password = false }, ] + depends_on = [time_sleep.wait_autokey_config] +} + +resource "google_kms_autokey_config" "autokey_config" { + provider = google-beta + folder = var.folder_id + key_project = "projects/${var.key_project_id}" +} + +resource "time_sleep" "wait_autokey_config" { + create_duration = "10s" + depends_on = [google_kms_autokey_config.autokey_config] } diff --git a/examples/postgresql-ha/outputs.tf b/examples/postgresql-ha/outputs.tf index d8cf998d..9459bbff 100644 --- a/examples/postgresql-ha/outputs.tf +++ b/examples/postgresql-ha/outputs.tf @@ -28,9 +28,11 @@ output "authorized_network" { } output "replicas" { - value = module.pg.replicas + value = module.pg.replicas + sensitive = true } output "instances" { - value = module.pg.instances + value = module.pg.instances + sensitive = true } diff --git a/examples/postgresql-ha/variables.tf b/examples/postgresql-ha/variables.tf index 311f951b..9c8ac7b3 100644 --- a/examples/postgresql-ha/variables.tf +++ b/examples/postgresql-ha/variables.tf @@ -30,3 +30,13 @@ variable "pg_ha_external_ip_range" { description = "The ip range to allow connecting from/to Cloud SQL" default = "192.10.10.10/32" } + +variable "key_project_id" { + type = string + description = "The project where autokey is setup" +} + +variable "folder_id" { + type = string + description = "The folder where project is created" +} diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index 600d709d..b761c0d3 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -170,6 +170,7 @@ module "pg" { | secondary\_zone | The preferred zone for the replica instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | | tier | The tier for the Cloud SQL instance. | `string` | `"db-f1-micro"` | no | | update\_timeout | The optional timout that is applied to limit long database updates. | `string` | `"30m"` | no | +| use\_autokey | Enable the use of autokeys from Google Cloud KMS for CMEK. This requires autokey already configured in the project. | `bool` | `false` | no | | user\_deletion\_policy | The deletion policy for the user. Setting ABANDON allows the resource to be abandoned rather than deleted. This is useful for Postgres, where users cannot be deleted from the API if they have been granted SQL roles. Possible values are: "ABANDON". | `string` | `null` | no | | user\_labels | The key/value labels for the Cloud SQL instances. | `map(string)` | `{}` | no | | user\_name | The name of the default user | `string` | `"default"` | no | diff --git a/modules/postgresql/main.tf b/modules/postgresql/main.tf index 4adf4e4d..a70e5526 100644 --- a/modules/postgresql/main.tf +++ b/modules/postgresql/main.tf @@ -45,6 +45,8 @@ locals { connector_enforcement = var.connector_enforcement ? "REQUIRED" : "NOT_REQUIRED" database_name = var.enable_default_db ? var.db_name : (length(var.additional_databases) > 0 ? var.additional_databases[0].name : "") + + encryption_key = var.encryption_key_name != null ? var.encryption_key_name : var.use_autokey ? google_kms_key_handle.default[0].kms_key : null } resource "random_id" "suffix" { @@ -60,7 +62,7 @@ resource "google_sql_database_instance" "default" { database_version = can(regex("\\d", substr(var.database_version, 0, 1))) ? format("POSTGRES_%s", var.database_version) : replace(var.database_version, substr(var.database_version, 0, 8), "POSTGRES") maintenance_version = var.maintenance_version region = var.region - encryption_key_name = var.encryption_key_name + encryption_key_name = local.encryption_key deletion_protection = var.deletion_protection root_password = var.root_password @@ -211,6 +213,15 @@ resource "google_sql_database_instance" "default" { depends_on = [null_resource.module_depends_on] } +resource "google_kms_key_handle" "default" { + count = var.use_autokey ? 1 : 0 + provider = google-beta + project = var.project_id + name = local.instance_name + location = coalesce(var.region, join("-", slice(split("-", var.zone), 0, 2))) + resource_type_selector = "sqladmin.googleapis.com/Instance" +} + resource "google_sql_database" "default" { count = var.enable_default_db ? 1 : 0 name = var.db_name diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index 05e44f1d..c3eb59bd 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -456,3 +456,9 @@ variable "database_integration_roles" { type = list(string) default = [] } + +variable "use_autokey" { + description = "Enable the use of autokeys from Google Cloud KMS for CMEK. This requires autokey already configured in the project." + type = bool + default = false +} diff --git a/test/fixtures/postgresql-ha/main.tf b/test/fixtures/postgresql-ha/main.tf index 7eac8778..9f8e55c4 100644 --- a/test/fixtures/postgresql-ha/main.tf +++ b/test/fixtures/postgresql-ha/main.tf @@ -32,7 +32,6 @@ module "example" { project_id = var.project_id pg_ha_name = var.pg_ha_name pg_ha_external_ip_range = var.pg_ha_external_ip_range + key_project_id = var.key_project_id + folder_id = var.folder_id } - - - diff --git a/test/fixtures/postgresql-ha/variables.tf b/test/fixtures/postgresql-ha/variables.tf index 3ad614b3..8fa1bd92 100644 --- a/test/fixtures/postgresql-ha/variables.tf +++ b/test/fixtures/postgresql-ha/variables.tf @@ -30,3 +30,13 @@ variable "pg_ha_external_ip_range" { description = "The ip range to allow connecting from/to Cloud SQL" default = "192.10.10.10/32" } + +variable "key_project_id" { + type = string + description = "The project where autokey is setup" +} + +variable "folder_id" { + type = string + description = "The folder where project is created" +} diff --git a/test/setup/iam.tf b/test/setup/iam.tf index 745def5f..951be51b 100644 --- a/test/setup/iam.tf +++ b/test/setup/iam.tf @@ -17,6 +17,7 @@ locals { int_required_roles = [ "roles/cloudkms.admin", + "roles/cloudkms.autokeyAdmin", "roles/cloudkms.cryptoKeyEncrypterDecrypter", "roles/cloudscheduler.admin", "roles/cloudsql.admin", @@ -45,6 +46,15 @@ resource "google_project_iam_member" "int_test" { member = "serviceAccount:${google_service_account.int_test.email}" } +resource "google_folder_iam_member" "int_test" { + count = length(local.int_required_roles) + + folder = google_folder.autokey_folder.folder_id + role = local.int_required_roles[count.index] + member = "serviceAccount:${google_service_account.int_test.email}" +} + + resource "google_service_account_key" "int_test" { service_account_id = google_service_account.int_test.id } diff --git a/test/setup/main.tf b/test/setup/main.tf index cf85e563..20f64c75 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -16,12 +16,12 @@ module "project" { source = "terraform-google-modules/project-factory/google" - version = "~> 17.0" + version = "~> 18.0" name = "ci-sql-db" random_project_id = "true" org_id = var.org_id - folder_id = var.folder_id + folder_id = google_folder.autokey_folder.folder_id billing_account = var.billing_account deletion_policy = "DELETE" @@ -54,3 +54,56 @@ resource "google_project_service_identity" "workflos_sa" { project = module.project.project_id service = "workflows.googleapis.com" } + +resource "google_folder" "autokey_folder" { + provider = google-beta + display_name = "ci-sql-db-folder" + parent = "folders/${var.folder_id}" + deletion_protection = false +} + +module "autokey-project" { + source = "terraform-google-modules/project-factory/google" + version = "~> 18.0" + + name = "ci-sql-db-autokey" + random_project_id = "true" + org_id = var.org_id + folder_id = google_folder.autokey_folder.folder_id + billing_account = var.billing_account + deletion_policy = "DELETE" + + activate_apis = [ + "cloudkms.googleapis.com", + ] +} + +resource "time_sleep" "wait_enable_service_api" { + depends_on = [module.autokey-project] + create_duration = "30s" +} + +resource "google_project_service_identity" "kms_service_agent" { + provider = google-beta + service = "cloudkms.googleapis.com" + project = module.autokey-project.project_id + depends_on = [time_sleep.wait_enable_service_api] +} + +resource "time_sleep" "wait_service_agent" { + depends_on = [google_project_service_identity.kms_service_agent] + create_duration = "10s" +} + +resource "google_project_iam_member" "autokey_project_admin" { + provider = google-beta + project = module.autokey-project.project_id + role = "roles/cloudkms.admin" + member = "serviceAccount:service-${module.autokey-project.project_number}@gcp-sa-cloudkms.iam.gserviceaccount.com" + depends_on = [time_sleep.wait_service_agent] +} + +resource "time_sleep" "wait_srv_acc_permissions" { + create_duration = "10s" + depends_on = [google_project_iam_member.autokey_project_admin] +} diff --git a/test/setup/outputs.tf b/test/setup/outputs.tf index 00f94d05..fa457d24 100644 --- a/test/setup/outputs.tf +++ b/test/setup/outputs.tf @@ -32,3 +32,11 @@ output "cloudsql_mysql_sa" { value = google_service_account.cloudsql_mysql_sa.email description = "IAM service account user created for Cloud SQL for MySql." } + +output "key_project_id" { + value = module.autokey-project.project_id +} + +output "folder_id" { + value = google_folder.autokey_folder.folder_id +} From f5ad3e6e09b040928f481b4b4f7cf0c56feda9d7 Mon Sep 17 00:00:00 2001 From: ykyr Date: Tue, 1 Apr 2025 19:10:25 +0200 Subject: [PATCH 04/17] feat: add setting enable_dataplex_integration (#713) Co-authored-by: Imran Nayer --- modules/mssql/README.md | 1 + modules/mssql/main.tf | 1 + modules/mssql/variables.tf | 6 ++++++ modules/mysql/README.md | 1 + modules/mysql/main.tf | 1 + modules/mysql/metadata.display.yaml | 3 +++ modules/mysql/metadata.yaml | 4 ++++ modules/mysql/variables.tf | 6 ++++++ modules/postgresql/README.md | 1 + modules/postgresql/main.tf | 1 + modules/postgresql/metadata.display.yaml | 3 +++ modules/postgresql/metadata.yaml | 4 ++++ modules/postgresql/variables.tf | 6 ++++++ 13 files changed, 38 insertions(+) diff --git a/modules/mssql/README.md b/modules/mssql/README.md index 29329a11..ecd25c0d 100644 --- a/modules/mssql/README.md +++ b/modules/mssql/README.md @@ -55,6 +55,7 @@ module "mssql" { | disk\_size | The disk size for the Cloud SQL instance. | `number` | `10` | no | | disk\_type | The disk type for the Cloud SQL instance. | `string` | `"PD_SSD"` | no | | edition | The edition of the instance, can be ENTERPRISE or ENTERPRISE\_PLUS. | `string` | `null` | no | +| enable\_dataplex\_integration | Enable database Dataplex integration | `bool` | `false` | no | | enable\_default\_db | Enable or disable the creation of the default database | `bool` | `true` | no | | enable\_default\_user | Enable or disable the creation of the default user | `bool` | `true` | no | | encryption\_key\_name | The full path to the encryption key used for the CMEK disk encryption | `string` | `null` | no | diff --git a/modules/mssql/main.tf b/modules/mssql/main.tf index 7464ce24..cb0a484b 100644 --- a/modules/mssql/main.tf +++ b/modules/mssql/main.tf @@ -62,6 +62,7 @@ resource "google_sql_database_instance" "default" { availability_type = var.availability_type deletion_protection_enabled = var.deletion_protection_enabled connector_enforcement = local.connector_enforcement + enable_dataplex_integration = var.enable_dataplex_integration dynamic "backup_configuration" { for_each = !local.is_secondary_instance && var.backup_configuration.enabled ? [var.backup_configuration] : [] diff --git a/modules/mssql/variables.tf b/modules/mssql/variables.tf index 4ff68872..5ddfea69 100644 --- a/modules/mssql/variables.tf +++ b/modules/mssql/variables.tf @@ -360,3 +360,9 @@ variable "enable_default_user" { type = bool default = true } + +variable "enable_dataplex_integration" { + description = "Enable database Dataplex integration" + type = bool + default = false +} diff --git a/modules/mysql/README.md b/modules/mysql/README.md index 064d6dcc..03128edc 100644 --- a/modules/mysql/README.md +++ b/modules/mysql/README.md @@ -68,6 +68,7 @@ module "mysql-db" { | disk\_size | The disk size (in GB) for the master instance | `number` | `10` | no | | disk\_type | The disk type for the master instance. | `string` | `"PD_SSD"` | no | | edition | The edition of the instance, can be ENTERPRISE or ENTERPRISE\_PLUS. | `string` | `null` | no | +| enable\_dataplex\_integration | Enable database Dataplex integration | `bool` | `false` | no | | enable\_default\_db | Enable or disable the creation of the default database | `bool` | `true` | no | | enable\_default\_user | Enable or disable the creation of the default user | `bool` | `true` | no | | enable\_google\_ml\_integration | Enable database ML integration | `bool` | `false` | no | diff --git a/modules/mysql/main.tf b/modules/mysql/main.tf index df17b938..b9d4ff08 100644 --- a/modules/mysql/main.tf +++ b/modules/mysql/main.tf @@ -72,6 +72,7 @@ resource "google_sql_database_instance" "default" { deletion_protection_enabled = var.deletion_protection_enabled connector_enforcement = local.connector_enforcement enable_google_ml_integration = var.enable_google_ml_integration + enable_dataplex_integration = var.enable_dataplex_integration dynamic "backup_configuration" { for_each = [var.backup_configuration] diff --git a/modules/mysql/metadata.display.yaml b/modules/mysql/metadata.display.yaml index 4847060b..71110e67 100644 --- a/modules/mysql/metadata.display.yaml +++ b/modules/mysql/metadata.display.yaml @@ -162,6 +162,9 @@ spec: enable_google_ml_integration: name: enable_google_ml_integration title: Enable Google Ml Integration + enable_dataplex_integration: + name: enable_dataplex_integration + title: Enable Dataplex Integration enable_random_password_special: name: enable_random_password_special title: Enable Random Password Special diff --git a/modules/mysql/metadata.yaml b/modules/mysql/metadata.yaml index 047e5c6d..32ef4a98 100644 --- a/modules/mysql/metadata.yaml +++ b/modules/mysql/metadata.yaml @@ -406,6 +406,10 @@ spec: description: Enable database ML integration varType: bool defaultValue: false + - name: enable_dataplex_integration + description: Enable database Dataplex integration + varType: bool + defaultValue: false - name: database_integration_roles description: The roles required by default database instance service account for integration with GCP services varType: list(string) diff --git a/modules/mysql/variables.tf b/modules/mysql/variables.tf index a3e540ae..0a79ec08 100644 --- a/modules/mysql/variables.tf +++ b/modules/mysql/variables.tf @@ -462,6 +462,12 @@ variable "enable_google_ml_integration" { default = false } +variable "enable_dataplex_integration" { + description = "Enable database Dataplex integration" + type = bool + default = false +} + variable "database_integration_roles" { description = "The roles required by default database instance service account for integration with GCP services" type = list(string) diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index b761c0d3..b911c399 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -140,6 +140,7 @@ module "pg" { | disk\_size | The disk size (in GB) for the Cloud SQL instance. | `number` | `10` | no | | disk\_type | The disk type for the Cloud SQL instance. | `string` | `"PD_SSD"` | no | | edition | The edition of the Cloud SQL instance, can be ENTERPRISE or ENTERPRISE\_PLUS. | `string` | `null` | no | +| enable\_dataplex\_integration | Enable database Dataplex integration | `bool` | `false` | no | | enable\_default\_db | Enable or disable the creation of the default database | `bool` | `true` | no | | enable\_default\_user | Enable or disable the creation of the default user | `bool` | `true` | no | | enable\_google\_ml\_integration | Enable database ML integration | `bool` | `false` | no | diff --git a/modules/postgresql/main.tf b/modules/postgresql/main.tf index a70e5526..f9f209c2 100644 --- a/modules/postgresql/main.tf +++ b/modules/postgresql/main.tf @@ -77,6 +77,7 @@ resource "google_sql_database_instance" "default" { deletion_protection_enabled = var.deletion_protection_enabled connector_enforcement = local.connector_enforcement enable_google_ml_integration = var.enable_google_ml_integration + enable_dataplex_integration = var.enable_dataplex_integration dynamic "backup_configuration" { for_each = local.is_secondary_instance ? [] : [var.backup_configuration] diff --git a/modules/postgresql/metadata.display.yaml b/modules/postgresql/metadata.display.yaml index 65b0aa20..55c7e3e6 100644 --- a/modules/postgresql/metadata.display.yaml +++ b/modules/postgresql/metadata.display.yaml @@ -170,6 +170,9 @@ spec: enable_google_ml_integration: name: enable_google_ml_integration title: Enable Google Ml Integration + enable_dataplex_integration: + name: enable_dataplex_integration + title: Enable Dataplex Integration enable_random_password_special: name: enable_random_password_special title: Enable Random Password Special diff --git a/modules/postgresql/metadata.yaml b/modules/postgresql/metadata.yaml index 6e21cd75..eaf73a95 100644 --- a/modules/postgresql/metadata.yaml +++ b/modules/postgresql/metadata.yaml @@ -396,6 +396,10 @@ spec: description: Enable database ML integration varType: bool defaultValue: false + - name: enable_dataplex_integration + description: Enable database Dataplex integration + varType: bool + defaultValue: false - name: database_integration_roles description: The roles required by default database instance service account for integration with GCP services varType: list(string) diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index c3eb59bd..44ecabef 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -451,6 +451,12 @@ variable "enable_google_ml_integration" { default = false } +variable "enable_dataplex_integration" { + description = "Enable database Dataplex integration" + type = bool + default = false +} + variable "database_integration_roles" { description = "The roles required by default database instance service account for integration with GCP services" type = list(string) From 923b7707ec468b25f4407f43d069e4124990e965 Mon Sep 17 00:00:00 2001 From: Philoj Johny Date: Wed, 9 Apr 2025 22:35:30 +0530 Subject: [PATCH 05/17] Fix: Postgres read-replica "psc_enabled" permadiff --- modules/postgresql/read_replica.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/postgresql/read_replica.tf b/modules/postgresql/read_replica.tf index c4fce644..516b308e 100644 --- a/modules/postgresql/read_replica.tf +++ b/modules/postgresql/read_replica.tf @@ -64,10 +64,10 @@ resource "google_sql_database_instance" "replicas" { } } dynamic "psc_config" { - for_each = ip_configuration.value.psc_enabled ? ["psc_enabled"] : [] + for_each = ip_configuration.value.psc_enabled ? ["psc_enabled"] : ["psc_disabled"] content { psc_enabled = ip_configuration.value.psc_enabled - allowed_consumer_projects = ip_configuration.value.psc_allowed_consumer_projects + allowed_consumer_projects = ip_configuration.value.psc_enabled ? ip_configuration.value.psc_allowed_consumer_projects : [] } } } From bca69c470464d7c6211008cd5c57d11dd1f4b6ce Mon Sep 17 00:00:00 2001 From: nagomiso Date: Wed, 16 Apr 2025 01:34:14 +0900 Subject: [PATCH 06/17] feat: Add output to retrieve passwords by user name for additional_users (#719) Co-authored-by: Imran Nayer --- modules/postgresql/README.md | 1 + modules/postgresql/outputs.tf | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index b911c399..b0a2b1f0 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -182,6 +182,7 @@ module "pg" { | Name | Description | |------|-------------| +| additional\_user\_passwords\_map | Map of auto generated passwords for the additional users | | additional\_users | List of maps of additional users and passwords | | apphub\_service\_uri | Service URI in CAIS style to be used by Apphub. | | dns\_name | DNS name of the instance endpoint | diff --git a/modules/postgresql/outputs.tf b/modules/postgresql/outputs.tf index fa14a0de..2d1b28b0 100644 --- a/modules/postgresql/outputs.tf +++ b/modules/postgresql/outputs.tf @@ -115,6 +115,12 @@ output "additional_users" { sensitive = true } +output "additional_user_passwords_map" { + description = "Map of auto generated passwords for the additional users" + value = { for u in google_sql_user.additional_users : u.name => u.password } + sensitive = true +} + output "iam_users" { description = "The list of the IAM users with access to the CloudSQL instance" value = var.iam_users From 7befe54c9f4c9b38f5f6ffc4c21da8e14e387119 Mon Sep 17 00:00:00 2001 From: Christophe Biguereau Date: Thu, 17 Apr 2025 14:22:50 +0200 Subject: [PATCH 07/17] fix: Disable SQL instance data_cache when data_cache_enabled variable is false (#720) Co-authored-by: Christophe BIGUEREAU Co-authored-by: Imran Nayer --- modules/mssql/main.tf | 2 +- modules/mysql/main.tf | 2 +- modules/postgresql/main.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/mssql/main.tf b/modules/mssql/main.tf index cb0a484b..ac99646c 100644 --- a/modules/mssql/main.tf +++ b/modules/mssql/main.tf @@ -83,7 +83,7 @@ resource "google_sql_database_instance" "default" { } } dynamic "data_cache_config" { - for_each = var.edition == "ENTERPRISE_PLUS" && var.data_cache_enabled ? ["cache_enabled"] : [] + for_each = var.edition == "ENTERPRISE_PLUS" ? ["cache_enabled"] : [] content { data_cache_enabled = var.data_cache_enabled } diff --git a/modules/mysql/main.tf b/modules/mysql/main.tf index b9d4ff08..5e5fb841 100644 --- a/modules/mysql/main.tf +++ b/modules/mysql/main.tf @@ -105,7 +105,7 @@ resource "google_sql_database_instance" "default" { } } dynamic "data_cache_config" { - for_each = var.edition == "ENTERPRISE_PLUS" && var.data_cache_enabled ? ["cache_enabled"] : [] + for_each = var.edition == "ENTERPRISE_PLUS" ? ["cache_enabled"] : [] content { data_cache_enabled = var.data_cache_enabled } diff --git a/modules/postgresql/main.tf b/modules/postgresql/main.tf index f9f209c2..bb9d4629 100644 --- a/modules/postgresql/main.tf +++ b/modules/postgresql/main.tf @@ -98,7 +98,7 @@ resource "google_sql_database_instance" "default" { } } dynamic "data_cache_config" { - for_each = var.edition == "ENTERPRISE_PLUS" && var.data_cache_enabled ? ["cache_enabled"] : [] + for_each = var.edition == "ENTERPRISE_PLUS" ? ["cache_enabled"] : [] content { data_cache_enabled = var.data_cache_enabled } From dd3b4dcc362dd7c6d26b6fd62490db989521dcd4 Mon Sep 17 00:00:00 2001 From: Imran Nayer Date: Sun, 20 Apr 2025 21:33:34 -0500 Subject: [PATCH 08/17] chore: fixed test setup (#726) --- test/setup/main.tf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/setup/main.tf b/test/setup/main.tf index 20f64c75..69a03212 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -55,9 +55,13 @@ resource "google_project_service_identity" "workflos_sa" { service = "workflows.googleapis.com" } +resource "random_id" "suffix" { + byte_length = 4 +} + resource "google_folder" "autokey_folder" { provider = google-beta - display_name = "ci-sql-db-folder" + display_name = "ci-sql-db-folder-${random_id.suffix.hex}" parent = "folders/${var.folder_id}" deletion_protection = false } From 056e436283f2802c8e00b3dd17390bff83f95d9b Mon Sep 17 00:00:00 2001 From: Park Chan Young Date: Fri, 25 Apr 2025 00:40:05 +0900 Subject: [PATCH 09/17] fix: replace invalid optional(string, ) with optional(string) (#725) Co-authored-by: Imran Nayer --- modules/mysql/README.md | 2 +- modules/mysql/metadata.yaml | 2 +- modules/mysql/variables.tf | 2 +- modules/postgresql/README.md | 2 +- modules/postgresql/metadata.yaml | 2 +- modules/postgresql/variables.tf | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/mysql/README.md b/modules/mysql/README.md index 03128edc..cc33ea04 100644 --- a/modules/mysql/README.md +++ b/modules/mysql/README.md @@ -93,7 +93,7 @@ module "mysql-db" { | read\_replica\_deletion\_protection | Used to block Terraform from deleting replica SQL Instances. | `bool` | `false` | no | | read\_replica\_deletion\_protection\_enabled | Enables protection of a read replica from accidental deletion across all surfaces (API, gcloud, Cloud Console and Terraform). | `bool` | `false` | no | | read\_replica\_name\_suffix | The optional suffix to add to the read instance name | `string` | `""` | no | -| read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = list(object({
name = string
value = string
}))
backup_configuration = optional(object({
binary_log_enabled = bool
transaction_log_retention_days = string
}))
insights_config = optional(object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
}))
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string, )
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
| `[]` | no | +| read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = list(object({
name = string
value = string
}))
backup_configuration = optional(object({
binary_log_enabled = bool
transaction_log_retention_days = string
}))
insights_config = optional(object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
}))
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
| `[]` | no | | region | The region of the Cloud SQL resources | `string` | `"us-central1"` | no | | replica\_database\_version | The read replica database version to use. This var should only be used during a database update. The update sequence 1. read-replica 2. master, setting this to an updated version will cause the replica to update, then you may update the master with the var database\_version and remove this field after update is complete | `string` | `""` | no | | root\_password | MySQL password for the root user. | `string` | `null` | no | diff --git a/modules/mysql/metadata.yaml b/modules/mysql/metadata.yaml index 32ef4a98..3918ac59 100644 --- a/modules/mysql/metadata.yaml +++ b/modules/mysql/metadata.yaml @@ -348,7 +348,7 @@ spec: ip_configuration = object({ authorized_networks = optional(list(map(string)), []) ipv4_enabled = optional(bool) - private_network = optional(string, ) + private_network = optional(string) ssl_mode = optional(string) allocated_ip_range = optional(string) enable_private_path_for_google_cloud_services = optional(bool, false) diff --git a/modules/mysql/variables.tf b/modules/mysql/variables.tf index 0a79ec08..50956ba8 100644 --- a/modules/mysql/variables.tf +++ b/modules/mysql/variables.tf @@ -377,7 +377,7 @@ variable "read_replicas" { ip_configuration = object({ authorized_networks = optional(list(map(string)), []) ipv4_enabled = optional(bool) - private_network = optional(string, ) + private_network = optional(string) ssl_mode = optional(string) allocated_ip_range = optional(string) enable_private_path_for_google_cloud_services = optional(bool, false) diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index b0a2b1f0..2b42482f 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -165,7 +165,7 @@ module "pg" { | read\_replica\_deletion\_protection | Used to block Terraform from deleting replica SQL Instances. | `bool` | `false` | no | | read\_replica\_deletion\_protection\_enabled | Enables protection of replica instance from accidental deletion across all surfaces (API, gcloud, Cloud Console and Terraform). | `bool` | `false` | no | | read\_replica\_name\_suffix | The optional suffix to add to the read instance name | `string` | `""` | no | -| read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = optional(list(object({
name = string
value = string
})), [])
insights_config = optional(object({
query_plans_per_minute = optional(number, 5)
query_string_length = optional(number, 1024)
record_application_tags = optional(bool, false)
record_client_address = optional(bool, false)
}), null)
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string, )
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
| `[]` | no | +| read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = optional(list(object({
name = string
value = string
})), [])
insights_config = optional(object({
query_plans_per_minute = optional(number, 5)
query_string_length = optional(number, 1024)
record_application_tags = optional(bool, false)
record_client_address = optional(bool, false)
}), null)
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
| `[]` | no | | region | The region of the Cloud SQL resources | `string` | `"us-central1"` | no | | root\_password | Initial root password during creation | `string` | `null` | no | | secondary\_zone | The preferred zone for the replica instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | diff --git a/modules/postgresql/metadata.yaml b/modules/postgresql/metadata.yaml index eaf73a95..d49b1f3a 100644 --- a/modules/postgresql/metadata.yaml +++ b/modules/postgresql/metadata.yaml @@ -313,7 +313,7 @@ spec: ip_configuration = object({ authorized_networks = optional(list(map(string)), []) ipv4_enabled = optional(bool) - private_network = optional(string, ) + private_network = optional(string) ssl_mode = optional(string) allocated_ip_range = optional(string) enable_private_path_for_google_cloud_services = optional(bool, false) diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index 44ecabef..95241e90 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -356,7 +356,7 @@ variable "read_replicas" { ip_configuration = object({ authorized_networks = optional(list(map(string)), []) ipv4_enabled = optional(bool) - private_network = optional(string, ) + private_network = optional(string) ssl_mode = optional(string) allocated_ip_range = optional(string) enable_private_path_for_google_cloud_services = optional(bool, false) From dee4d744cb82dac97f845b2450eca732a226b3bb Mon Sep 17 00:00:00 2001 From: amrkk123 Date: Fri, 25 Apr 2025 12:38:27 +0000 Subject: [PATCH 10/17] chore: Change description for tier in mysql and cloud sql (#724) Co-authored-by: Imran Nayer --- modules/mysql/README.md | 2 +- modules/mysql/metadata.yaml | 3 ++- modules/mysql/variables.tf | 2 +- modules/postgresql/README.md | 2 +- modules/postgresql/metadata.yaml | 9 ++++++++- modules/postgresql/variables.tf | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/modules/mysql/README.md b/modules/mysql/README.md index cc33ea04..fd04ca34 100644 --- a/modules/mysql/README.md +++ b/modules/mysql/README.md @@ -98,7 +98,7 @@ module "mysql-db" { | replica\_database\_version | The read replica database version to use. This var should only be used during a database update. The update sequence 1. read-replica 2. master, setting this to an updated version will cause the replica to update, then you may update the master with the var database\_version and remove this field after update is complete | `string` | `""` | no | | root\_password | MySQL password for the root user. | `string` | `null` | no | | secondary\_zone | The preferred zone for the secondary/failover instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | -| tier | The tier for the master instance. | `string` | `"db-n1-standard-1"` | no | +| tier | The tier for the master instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE\_PLUS, if user wants to change the edition, he should chose compatible tier. | `string` | `"db-n1-standard-1"` | no | | update\_timeout | The optional timout that is applied to limit long database updates. | `string` | `"30m"` | no | | user\_deletion\_policy | The deletion policy for the user. Setting ABANDON allows the resource to be abandoned rather than deleted. This is useful for Postgres, where users cannot be deleted from the API if they have been granted SQL roles. Possible values are: "ABANDON". | `string` | `null` | no | | user\_host | The host for the default user | `string` | `"%"` | no | diff --git a/modules/mysql/metadata.yaml b/modules/mysql/metadata.yaml index 3918ac59..22cd2856 100644 --- a/modules/mysql/metadata.yaml +++ b/modules/mysql/metadata.yaml @@ -186,7 +186,7 @@ spec: description: Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of instance_type. To promote, users have to set the instance_type property as CLOUD_SQL_INSTANCE and remove/unset master_instance_name and replica_configuration from instance configuration. This operation might cause your instance to restart. varType: string - name: tier - description: The tier for the master instance. + description: The tier for the master instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE_PLUS, if user wants to change the edition, he should chose compatible tier. varType: string defaultValue: db-n1-standard-1 - name: zone @@ -912,6 +912,7 @@ spec: - level: Project roles: - roles/cloudkms.admin + - roles/cloudkms.autokeyAdmin - roles/cloudkms.cryptoKeyEncrypterDecrypter - roles/cloudscheduler.admin - roles/cloudsql.admin diff --git a/modules/mysql/variables.tf b/modules/mysql/variables.tf index 50956ba8..500cff56 100644 --- a/modules/mysql/variables.tf +++ b/modules/mysql/variables.tf @@ -178,7 +178,7 @@ variable "instance_type" { // Master variable "tier" { - description = "The tier for the master instance." + description = "The tier for the master instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE_PLUS, if user wants to change the edition, he should chose compatible tier." type = string default = "db-n1-standard-1" } diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index 2b42482f..e9b83d3d 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -169,7 +169,7 @@ module "pg" { | region | The region of the Cloud SQL resources | `string` | `"us-central1"` | no | | root\_password | Initial root password during creation | `string` | `null` | no | | secondary\_zone | The preferred zone for the replica instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | -| tier | The tier for the Cloud SQL instance. | `string` | `"db-f1-micro"` | no | +| tier | The tier for the Cloud SQL instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE\_PLUS, if user wants to change the edition, he should chose compatible tier. | `string` | `"db-f1-micro"` | no | | update\_timeout | The optional timout that is applied to limit long database updates. | `string` | `"30m"` | no | | use\_autokey | Enable the use of autokeys from Google Cloud KMS for CMEK. This requires autokey already configured in the project. | `bool` | `false` | no | | user\_deletion\_policy | The deletion policy for the user. Setting ABANDON allows the resource to be abandoned rather than deleted. This is useful for Postgres, where users cannot be deleted from the API if they have been granted SQL roles. Possible values are: "ABANDON". | `string` | `null` | no | diff --git a/modules/postgresql/metadata.yaml b/modules/postgresql/metadata.yaml index d49b1f3a..e9572116 100644 --- a/modules/postgresql/metadata.yaml +++ b/modules/postgresql/metadata.yaml @@ -163,7 +163,7 @@ spec: varType: bool defaultValue: false - name: tier - description: The tier for the Cloud SQL instance. + description: The tier for the Cloud SQL instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE_PLUS, if user wants to change the edition, he should chose compatible tier. varType: string defaultValue: db-f1-micro - name: zone @@ -404,7 +404,13 @@ spec: description: The roles required by default database instance service account for integration with GCP services varType: list(string) defaultValue: [] + - name: use_autokey + description: Enable the use of autokeys from Google Cloud KMS for CMEK. This requires autokey already configured in the project. + varType: bool + defaultValue: false outputs: + - name: additional_user_passwords_map + description: Map of auto generated passwords for the additional users - name: additional_users description: List of maps of additional users and passwords type: @@ -902,6 +908,7 @@ spec: - level: Project roles: - roles/cloudkms.admin + - roles/cloudkms.autokeyAdmin - roles/cloudkms.cryptoKeyEncrypterDecrypter - roles/cloudscheduler.admin - roles/cloudsql.admin diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index 95241e90..c7172a8d 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -171,7 +171,7 @@ variable "random_instance_name" { } variable "tier" { - description = "The tier for the Cloud SQL instance." + description = "The tier for the Cloud SQL instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE_PLUS, if user wants to change the edition, he should chose compatible tier." type = string default = "db-f1-micro" } From af7f20c466b292a6d210a2c21c877d72d46536ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mitka?= <75326685+lukasz-mitka@users.noreply.github.com> Date: Tue, 29 Apr 2025 02:03:47 +0200 Subject: [PATCH 11/17] feat: Remove condition from data.google_compute_zones.available (#684) Co-authored-by: Imran Nayer --- modules/postgresql/read_replica.tf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/postgresql/read_replica.tf b/modules/postgresql/read_replica.tf index 516b308e..3cae2aa1 100644 --- a/modules/postgresql/read_replica.tf +++ b/modules/postgresql/read_replica.tf @@ -19,11 +19,10 @@ locals { for x in var.read_replicas : "${var.name}-replica${var.read_replica_name_suffix}${x.name}" => x } // Zone for replica instances - zone = var.zone == null ? data.google_compute_zones.available[0].names[0] : var.zone + zone = var.zone == null ? data.google_compute_zones.available.names[0] : var.zone } data "google_compute_zones" "available" { - count = var.zone == null ? 1 : 0 project = var.project_id region = var.region } From 90a3e64bc9da13885f1fa33ed0f5a24edb1406a7 Mon Sep 17 00:00:00 2001 From: wnugent Date: Wed, 21 May 2025 14:24:49 +0100 Subject: [PATCH 12/17] feat(TPG>6.17)!: Adding new variables to define failover dr replica (#728) --- docs/upgrading_to_sql_db_26.0.md | 5 +++++ modules/mysql/README.md | 1 + modules/mysql/main.tf | 7 +++++++ modules/mysql/metadata.yaml | 3 +++ modules/mysql/variables.tf | 7 +++++++ modules/mysql/versions.tf | 4 ++-- modules/postgresql/README.md | 1 + modules/postgresql/main.tf | 7 +++++++ modules/postgresql/metadata.yaml | 3 +++ modules/postgresql/variables.tf | 6 ++++++ modules/postgresql/versions.tf | 4 ++-- modules/safer_mysql/README.md | 3 +++ modules/safer_mysql/main.tf | 3 +++ modules/safer_mysql/metadata.yaml | 9 +++++++++ modules/safer_mysql/variables.tf | 21 +++++++++++++++++++++ modules/safer_mysql/versions.tf | 2 +- 16 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 docs/upgrading_to_sql_db_26.0.md diff --git a/docs/upgrading_to_sql_db_26.0.md b/docs/upgrading_to_sql_db_26.0.md new file mode 100644 index 00000000..957021a0 --- /dev/null +++ b/docs/upgrading_to_sql_db_26.0.md @@ -0,0 +1,5 @@ +# Upgrading to v26.0 + +The v26.0 release contains backwards-incompatible changes. + +This update requires upgrading the minimum provider version from `6.1` to `6.17` diff --git a/modules/mysql/README.md b/modules/mysql/README.md index fd04ca34..c1422e23 100644 --- a/modules/mysql/README.md +++ b/modules/mysql/README.md @@ -74,6 +74,7 @@ module "mysql-db" { | enable\_google\_ml\_integration | Enable database ML integration | `bool` | `false` | no | | enable\_random\_password\_special | Enable special characters in generated random passwords. | `bool` | `false` | no | | encryption\_key\_name | The full path to the encryption key used for the CMEK disk encryption | `string` | `null` | no | +| failover\_dr\_replica\_name | If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is "your-project:your-instance". You can also set this field to "your-instance", but cloud SQL backend will convert it to the aforementioned standard format. | `string` | `null` | no | | follow\_gae\_application | A Google App Engine application whose zone to remain in. Must be in the same region as this instance. | `string` | `null` | no | | iam\_users | A list of IAM users to be created in your CloudSQL instance. iam.users.type can be CLOUD\_IAM\_USER, CLOUD\_IAM\_SERVICE\_ACCOUNT, CLOUD\_IAM\_GROUP and is required for type CLOUD\_IAM\_GROUP (IAM groups) |
list(object({
id = string,
email = string,
type = optional(string)
}))
| `[]` | no | | insights\_config | The insights\_config settings for the database. |
object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
})
| `null` | no | diff --git a/modules/mysql/main.tf b/modules/mysql/main.tf index 5e5fb841..bd14dbd8 100644 --- a/modules/mysql/main.tf +++ b/modules/mysql/main.tf @@ -64,6 +64,13 @@ resource "google_sql_database_instance" "default" { deletion_protection = var.deletion_protection root_password = var.root_password == "" ? null : var.root_password + dynamic "replication_cluster" { + for_each = var.failover_dr_replica_name != null ? [var.failover_dr_replica_name] : [] + content { + failover_dr_replica_name = var.failover_dr_replica_name + } + } + settings { tier = var.tier edition = var.edition diff --git a/modules/mysql/metadata.yaml b/modules/mysql/metadata.yaml index 22cd2856..8acaf37c 100644 --- a/modules/mysql/metadata.yaml +++ b/modules/mysql/metadata.yaml @@ -182,6 +182,9 @@ spec: - name: master_instance_name description: The name of the existing instance that will act as the master in the replication setup. varType: string + - name: failover_dr_replica_name + description: If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is "your-project:your-instance". You can also set this field to "your-instance", but cloud SQL backend will convert it to the aforementioned standard format. + varType: string - name: instance_type description: Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of instance_type. To promote, users have to set the instance_type property as CLOUD_SQL_INSTANCE and remove/unset master_instance_name and replica_configuration from instance configuration. This operation might cause your instance to restart. varType: string diff --git a/modules/mysql/variables.tf b/modules/mysql/variables.tf index 500cff56..2be0451e 100644 --- a/modules/mysql/variables.tf +++ b/modules/mysql/variables.tf @@ -169,6 +169,13 @@ variable "master_instance_name" { default = null } +//optional +variable "failover_dr_replica_name" { + type = string + description = "If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is \"your-project:your-instance\". You can also set this field to \"your-instance\", but cloud SQL backend will convert it to the aforementioned standard format." + default = null +} + // optional variable "instance_type" { description = "Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of instance_type. To promote, users have to set the instance_type property as CLOUD_SQL_INSTANCE and remove/unset master_instance_name and replica_configuration from instance configuration. This operation might cause your instance to restart." diff --git a/modules/mysql/versions.tf b/modules/mysql/versions.tf index d81c8469..ab1c32bd 100644 --- a/modules/mysql/versions.tf +++ b/modules/mysql/versions.tf @@ -27,11 +27,11 @@ terraform { } google = { source = "hashicorp/google" - version = ">= 6.1, < 7" + version = ">= 6.17, < 7" } google-beta = { source = "hashicorp/google-beta" - version = ">= 6.1, < 7" + version = ">= 6.17, < 7" } } diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index e9b83d3d..9b9a7859 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -146,6 +146,7 @@ module "pg" { | enable\_google\_ml\_integration | Enable database ML integration | `bool` | `false` | no | | enable\_random\_password\_special | Enable special characters in generated random passwords. | `bool` | `false` | no | | encryption\_key\_name | The full path to the encryption key used for the CMEK disk encryption | `string` | `null` | no | +| failover\_dr\_replica\_name | If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is "your-project:your-instance". You can also set this field to "your-instance", but cloud SQL backend will convert it to the aforementioned standard format. | `string` | `null` | no | | follow\_gae\_application | A Google App Engine application whose zone to remain in. Must be in the same region as this instance. | `string` | `null` | no | | iam\_users | A list of IAM users to be created in your CloudSQL instance. iam.users.type can be CLOUD\_IAM\_USER, CLOUD\_IAM\_SERVICE\_ACCOUNT, CLOUD\_IAM\_GROUP and is required for type CLOUD\_IAM\_GROUP (IAM groups) |
list(object({
id = string,
email = string,
type = optional(string)
}))
| `[]` | no | | insights\_config | The insights\_config settings for the database. |
object({
query_plans_per_minute = optional(number, 5)
query_string_length = optional(number, 1024)
record_application_tags = optional(bool, false)
record_client_address = optional(bool, false)
})
| `null` | no | diff --git a/modules/postgresql/main.tf b/modules/postgresql/main.tf index bb9d4629..4b4fd2aa 100644 --- a/modules/postgresql/main.tf +++ b/modules/postgresql/main.tf @@ -69,6 +69,13 @@ resource "google_sql_database_instance" "default" { master_instance_name = var.master_instance_name instance_type = local.is_secondary_instance ? "READ_REPLICA_INSTANCE" : var.instance_type + dynamic "replication_cluster" { + for_each = var.failover_dr_replica_name != null ? [var.failover_dr_replica_name] : [] + content { + failover_dr_replica_name = var.failover_dr_replica_name + } + } + settings { tier = var.tier edition = var.edition diff --git a/modules/postgresql/metadata.yaml b/modules/postgresql/metadata.yaml index e9572116..a9bd516c 100644 --- a/modules/postgresql/metadata.yaml +++ b/modules/postgresql/metadata.yaml @@ -154,6 +154,9 @@ spec: - name: master_instance_name description: Name of the master instance if this is a failover replica. Required for creating failover replica instance. Not needed for master instance. When removed, next terraform apply will promote this failover failover replica instance as master instance varType: string + - name: failover_dr_replica_name + description: If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is "your-project:your-instance". You can also set this field to "your-instance", but cloud SQL backend will convert it to the aforementioned standard format. + varType: string - name: instance_type description: The type of the instance. The supported values are SQL_INSTANCE_TYPE_UNSPECIFIED, CLOUD_SQL_INSTANCE, ON_PREMISES_INSTANCE and READ_REPLICA_INSTANCE. Set to READ_REPLICA_INSTANCE if master_instance_name value is provided varType: string diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index c7172a8d..e05b5844 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -158,6 +158,12 @@ variable "master_instance_name" { default = null } +variable "failover_dr_replica_name" { + type = string + description = "If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is \"your-project:your-instance\". You can also set this field to \"your-instance\", but cloud SQL backend will convert it to the aforementioned standard format." + default = null +} + variable "instance_type" { type = string description = "The type of the instance. The supported values are SQL_INSTANCE_TYPE_UNSPECIFIED, CLOUD_SQL_INSTANCE, ON_PREMISES_INSTANCE and READ_REPLICA_INSTANCE. Set to READ_REPLICA_INSTANCE if master_instance_name value is provided" diff --git a/modules/postgresql/versions.tf b/modules/postgresql/versions.tf index 820655c0..5700838a 100644 --- a/modules/postgresql/versions.tf +++ b/modules/postgresql/versions.tf @@ -27,11 +27,11 @@ terraform { } google = { source = "hashicorp/google" - version = ">= 6.1, < 7" + version = ">= 6.17, < 7" } google-beta = { source = "hashicorp/google-beta" - version = ">= 6.1, < 7" + version = ">= 6.17, < 7" } } diff --git a/modules/safer_mysql/README.md b/modules/safer_mysql/README.md index 0fb9b364..a64f2486 100644 --- a/modules/safer_mysql/README.md +++ b/modules/safer_mysql/README.md @@ -264,13 +264,16 @@ module "safer-mysql-db" { | enable\_default\_db | Enable or disable the creation of the default database | `bool` | `true` | no | | enable\_default\_user | Enable or disable the creation of the default user | `bool` | `true` | no | | encryption\_key\_name | The full path to the encryption key used for the CMEK disk encryption | `string` | `null` | no | +| failover\_dr\_replica\_name | If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is "your-project:your-instance". You can also set this field to "your-instance", but cloud SQL backend will convert it to the aforementioned standard format. | `string` | `null` | no | | follow\_gae\_application | A Google App Engine application whose zone to remain in. Must be in the same region as this instance. | `string` | `null` | no | | iam\_users | A list of IAM users to be created in your CloudSQL instance. iam.users.type can be CLOUD\_IAM\_USER, CLOUD\_IAM\_SERVICE\_ACCOUNT, CLOUD\_IAM\_GROUP and is required for type CLOUD\_IAM\_GROUP (IAM groups) |
list(object({
id = string,
email = string,
type = optional(string)
}))
| `[]` | no | | insights\_config | The insights\_config settings for the database. |
object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
})
| `null` | no | +| instance\_type | Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of instance\_type. To promote, users have to set the instance\_type property as CLOUD\_SQL\_INSTANCE and remove/unset master\_instance\_name and replica\_configuration from instance configuration. This operation might cause your instance to restart. | `string` | `null` | no | | maintenance\_version | The current software version on the instance. This attribute can not be set during creation. Refer to available\_maintenance\_versions attribute to see what maintenance\_version are available for upgrade. When this attribute gets updated, it will cause an instance restart. Setting a maintenance\_version value that is older than the current one on the instance will be ignored | `string` | `null` | no | | maintenance\_window\_day | The day of week (1-7) for the master instance maintenance. | `number` | `1` | no | | maintenance\_window\_hour | The hour of day (0-23) maintenance window for the master instance maintenance. | `number` | `23` | no | | maintenance\_window\_update\_track | The update track of maintenance window for the master instance maintenance. Can be either `canary` or `stable`. | `string` | `"stable"` | no | +| master\_instance\_name | The name of the existing instance that will act as the master in the replication setup. | `string` | `null` | no | | module\_depends\_on | List of modules or resources this module depends on. | `list(any)` | `[]` | no | | name | The name of the Cloud SQL resources | `string` | n/a | yes | | pricing\_plan | The pricing plan for the master instance. | `string` | `"PER_USE"` | no | diff --git a/modules/safer_mysql/main.tf b/modules/safer_mysql/main.tf index 974556ff..d3e784cf 100644 --- a/modules/safer_mysql/main.tf +++ b/modules/safer_mysql/main.tf @@ -24,6 +24,9 @@ module "safer_mysql" { region = var.region zone = var.zone secondary_zone = var.secondary_zone + master_instance_name = var.master_instance_name + failover_dr_replica_name = var.failover_dr_replica_name + instance_type = var.instance_type follow_gae_application = var.follow_gae_application tier = var.tier edition = var.edition diff --git a/modules/safer_mysql/metadata.yaml b/modules/safer_mysql/metadata.yaml index f5494ae8..26e0b6e5 100644 --- a/modules/safer_mysql/metadata.yaml +++ b/modules/safer_mysql/metadata.yaml @@ -192,6 +192,9 @@ spec: - name: encryption_key_name description: The full path to the encryption key used for the CMEK disk encryption varType: string + - name: failover_dr_replica_name + description: If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is "your-project:your-instance". You can also set this field to "your-instance", but cloud SQL backend will convert it to the aforementioned standard format. + varType: string - name: follow_gae_application description: A Google App Engine application whose zone to remain in. Must be in the same region as this instance. varType: string @@ -212,6 +215,9 @@ spec: record_application_tags = bool record_client_address = bool }) + - name: instance_type + description: Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of instance_type. To promote, users have to set the instance_type property as CLOUD_SQL_INSTANCE and remove/unset master_instance_name and replica_configuration from instance configuration. This operation might cause your instance to restart. + varType: string - name: maintenance_window_day description: The day of week (1-7) for the master instance maintenance. varType: number @@ -224,6 +230,9 @@ spec: description: The update track of maintenance window for the master instance maintenance. Can be either `canary` or `stable`. varType: string defaultValue: stable + - name: master_instance_name + description: The name of the existing instance that will act as the master in the replication setup. + varType: string - name: module_depends_on description: List of modules or resources this module depends on. varType: list(any) diff --git a/modules/safer_mysql/variables.tf b/modules/safer_mysql/variables.tf index 3cf1f886..33e37357 100644 --- a/modules/safer_mysql/variables.tf +++ b/modules/safer_mysql/variables.tf @@ -85,6 +85,27 @@ variable "secondary_zone" { default = null } +// optional +variable "master_instance_name" { + description = "The name of the existing instance that will act as the master in the replication setup." + type = string + default = null +} + +//optional +variable "failover_dr_replica_name" { + type = string + description = "If the instance is a primary instance, then this field identifies the disaster recovery (DR) replica. The standard format of this field is \"your-project:your-instance\". You can also set this field to \"your-instance\", but cloud SQL backend will convert it to the aforementioned standard format." + default = null +} + +// optional +variable "instance_type" { + description = "Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of instance_type. To promote, users have to set the instance_type property as CLOUD_SQL_INSTANCE and remove/unset master_instance_name and replica_configuration from instance configuration. This operation might cause your instance to restart." + type = string + default = null +} + variable "follow_gae_application" { type = string description = "A Google App Engine application whose zone to remain in. Must be in the same region as this instance." diff --git a/modules/safer_mysql/versions.tf b/modules/safer_mysql/versions.tf index bc5f2f40..d20bdb38 100644 --- a/modules/safer_mysql/versions.tf +++ b/modules/safer_mysql/versions.tf @@ -20,7 +20,7 @@ terraform { google = { source = "hashicorp/google" - version = ">= 6.1, < 7" + version = ">= 6.17, < 7" } } From edc7ee79d66658c4458a50c83e2164c0b3da0e67 Mon Sep 17 00:00:00 2001 From: Oscar van Leusen Date: Wed, 21 May 2025 18:57:28 +0100 Subject: [PATCH 13/17] fix: truncate service account display_name in backup module (#734) Co-authored-by: Imran Nayer --- modules/backup/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/backup/main.tf b/modules/backup/main.tf index 872d4566..f4a6b78b 100644 --- a/modules/backup/main.tf +++ b/modules/backup/main.tf @@ -33,7 +33,7 @@ locals { resource "google_service_account" "sql_backup_serviceaccount" { count = local.create_service_account ? 1 : 0 account_id = trimsuffix(substr("backup-${var.sql_instance}", 0, 28), "-") - display_name = "Managed by Terraform - Service account for backup of SQL Instance ${var.sql_instance}" + display_name = substr("Managed by Terraform - Service account for backup of SQL Instance ${var.sql_instance}", 0, 100) project = var.project_id } From 15e8be86f3ea98b36cb3e736c3494c1f40b30e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Hoste?= Date: Thu, 12 Jun 2025 14:47:59 +0200 Subject: [PATCH 14/17] feat: add support for server_ca_mode and custom SANs (#714) (#736) --- modules/postgresql/README.md | 2 +- modules/postgresql/main.tf | 3 +++ modules/postgresql/variables.tf | 3 +++ modules/postgresql/versions.tf | 4 ++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index 9b9a7859..11bc5066 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -151,7 +151,7 @@ module "pg" { | iam\_users | A list of IAM users to be created in your CloudSQL instance. iam.users.type can be CLOUD\_IAM\_USER, CLOUD\_IAM\_SERVICE\_ACCOUNT, CLOUD\_IAM\_GROUP and is required for type CLOUD\_IAM\_GROUP (IAM groups) |
list(object({
id = string,
email = string,
type = optional(string)
}))
| `[]` | no | | insights\_config | The insights\_config settings for the database. |
object({
query_plans_per_minute = optional(number, 5)
query_string_length = optional(number, 1024)
record_application_tags = optional(bool, false)
record_client_address = optional(bool, false)
})
| `null` | no | | instance\_type | The type of the instance. The supported values are SQL\_INSTANCE\_TYPE\_UNSPECIFIED, CLOUD\_SQL\_INSTANCE, ON\_PREMISES\_INSTANCE and READ\_REPLICA\_INSTANCE. Set to READ\_REPLICA\_INSTANCE if master\_instance\_name value is provided | `string` | `"CLOUD_SQL_INSTANCE"` | no | -| ip\_configuration | The ip configuration for the Cloud SQL instances. |
object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool, true)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
| `{}` | no | +| ip\_configuration | The ip configuration for the Cloud SQL instances. |
object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool, true)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
server_ca_mode = optional(string)
server_ca_pool = optional(string)
custom_subject_alternative_names = optional(list(string), [])
})
| `{}` | no | | maintenance\_version | The current software version on the instance. This attribute can not be set during creation. Refer to available\_maintenance\_versions attribute to see what maintenance\_version are available for upgrade. When this attribute gets updated, it will cause an instance restart. Setting a maintenance\_version value that is older than the current one on the instance will be ignored | `string` | `null` | no | | maintenance\_window\_day | The day of week (1-7) for the Cloud SQL instance maintenance. | `number` | `1` | no | | maintenance\_window\_hour | The hour of day (0-23) maintenance window for the Cloud SQL instance maintenance. | `number` | `23` | no | diff --git a/modules/postgresql/main.tf b/modules/postgresql/main.tf index 4b4fd2aa..a8284879 100644 --- a/modules/postgresql/main.tf +++ b/modules/postgresql/main.tf @@ -126,6 +126,9 @@ resource "google_sql_database_instance" "default" { ssl_mode = lookup(ip_configuration.value, "ssl_mode", null) allocated_ip_range = lookup(ip_configuration.value, "allocated_ip_range", null) enable_private_path_for_google_cloud_services = lookup(ip_configuration.value, "enable_private_path_for_google_cloud_services", false) + server_ca_mode = lookup(ip_configuration.value, "server_ca_mode", null) + server_ca_pool = lookup(ip_configuration.value, "server_ca_pool", null) + custom_subject_alternative_names = lookup(ip_configuration.value, "custom_subject_alternative_names", []) dynamic "authorized_networks" { for_each = lookup(ip_configuration.value, "authorized_networks", []) diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index e05b5844..6596b0e8 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -330,6 +330,9 @@ variable "ip_configuration" { enable_private_path_for_google_cloud_services = optional(bool, false) psc_enabled = optional(bool, false) psc_allowed_consumer_projects = optional(list(string), []) + server_ca_mode = optional(string) + server_ca_pool = optional(string) + custom_subject_alternative_names = optional(list(string), []) }) default = {} } diff --git a/modules/postgresql/versions.tf b/modules/postgresql/versions.tf index 5700838a..c0e950d1 100644 --- a/modules/postgresql/versions.tf +++ b/modules/postgresql/versions.tf @@ -27,11 +27,11 @@ terraform { } google = { source = "hashicorp/google" - version = ">= 6.17, < 7" + version = ">= 6.31, < 7" } google-beta = { source = "hashicorp/google-beta" - version = ">= 6.17, < 7" + version = ">= 6.31, < 7" } } From d0b31dd44d23465df72a91d50755d1209e6c4bdc Mon Sep 17 00:00:00 2001 From: Oscar van Leusen Date: Tue, 17 Jun 2025 19:07:25 +0100 Subject: [PATCH 15/17] feat(TPG>6.31)!: Support retain_backups_on_delete for mysql, safer_mysql (#735) Co-authored-by: Imran Nayer --- modules/mysql/README.md | 1 + modules/mysql/main.tf | 1 + modules/mysql/variables.tf | 7 +++++++ modules/mysql/versions.tf | 4 ++-- modules/safer_mysql/README.md | 1 + modules/safer_mysql/main.tf | 3 ++- modules/safer_mysql/variables.tf | 6 ++++++ modules/safer_mysql/versions.tf | 2 +- 8 files changed, 21 insertions(+), 4 deletions(-) diff --git a/modules/mysql/README.md b/modules/mysql/README.md index c1422e23..371926e0 100644 --- a/modules/mysql/README.md +++ b/modules/mysql/README.md @@ -97,6 +97,7 @@ module "mysql-db" { | read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = list(object({
name = string
value = string
}))
backup_configuration = optional(object({
binary_log_enabled = bool
transaction_log_retention_days = string
}))
insights_config = optional(object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
}))
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
| `[]` | no | | region | The region of the Cloud SQL resources | `string` | `"us-central1"` | no | | replica\_database\_version | The read replica database version to use. This var should only be used during a database update. The update sequence 1. read-replica 2. master, setting this to an updated version will cause the replica to update, then you may update the master with the var database\_version and remove this field after update is complete | `string` | `""` | no | +| retain\_backups\_on\_delete | When this parameter is set to true, Cloud SQL retains backups of the instance even after the instance is deleted. The ON\_DEMAND backup will be retained until customer deletes the backup or the project. The AUTOMATED backup will be retained based on the backups retention setting. | `bool` | `false` | no | | root\_password | MySQL password for the root user. | `string` | `null` | no | | secondary\_zone | The preferred zone for the secondary/failover instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | | tier | The tier for the master instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE\_PLUS, if user wants to change the edition, he should chose compatible tier. | `string` | `"db-n1-standard-1"` | no | diff --git a/modules/mysql/main.tf b/modules/mysql/main.tf index bd14dbd8..57158479 100644 --- a/modules/mysql/main.tf +++ b/modules/mysql/main.tf @@ -80,6 +80,7 @@ resource "google_sql_database_instance" "default" { connector_enforcement = local.connector_enforcement enable_google_ml_integration = var.enable_google_ml_integration enable_dataplex_integration = var.enable_dataplex_integration + retain_backups_on_delete = var.retain_backups_on_delete dynamic "backup_configuration" { for_each = [var.backup_configuration] diff --git a/modules/mysql/variables.tf b/modules/mysql/variables.tf index 2be0451e..db742727 100644 --- a/modules/mysql/variables.tf +++ b/modules/mysql/variables.tf @@ -314,6 +314,12 @@ variable "backup_configuration" { default = {} } +variable "retain_backups_on_delete" { + description = "When this parameter is set to true, Cloud SQL retains backups of the instance even after the instance is deleted. The ON_DEMAND backup will be retained until customer deletes the backup or the project. The AUTOMATED backup will be retained based on the backups retention setting." + type = bool + default = false +} + variable "insights_config" { description = "The insights_config settings for the database." type = object({ @@ -480,3 +486,4 @@ variable "database_integration_roles" { type = list(string) default = [] } + diff --git a/modules/mysql/versions.tf b/modules/mysql/versions.tf index ab1c32bd..fd61ed03 100644 --- a/modules/mysql/versions.tf +++ b/modules/mysql/versions.tf @@ -27,11 +27,11 @@ terraform { } google = { source = "hashicorp/google" - version = ">= 6.17, < 7" + version = ">= 6.31, < 7" } google-beta = { source = "hashicorp/google-beta" - version = ">= 6.17, < 7" + version = ">= 6.31, < 7" } } diff --git a/modules/safer_mysql/README.md b/modules/safer_mysql/README.md index a64f2486..c0b9de04 100644 --- a/modules/safer_mysql/README.md +++ b/modules/safer_mysql/README.md @@ -284,6 +284,7 @@ module "safer-mysql-db" { | read\_replica\_name\_suffix | The optional suffix to add to the read instance name | `string` | `""` | no | | read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = string
edition = string
availability_type = string
zone = string
disk_type = string
disk_autoresize = bool
disk_autoresize_limit = number
disk_size = string
user_labels = map(string)
database_flags = list(object({
name = string
value = string
}))
insights_config = optional(object({
query_plans_per_minute = number
query_string_length = number
record_application_tags = bool
record_client_address = bool
}))
ip_configuration = object({
authorized_networks = list(map(string))
ipv4_enabled = bool
private_network = string
allocated_ip_range = string
})
encryption_key_name = string
}))
| `[]` | no | | region | The region of the Cloud SQL resources | `string` | n/a | yes | +| retain\_backups\_on\_delete | When this parameter is set to true, Cloud SQL retains backups of the instance even after the instance is deleted. The ON\_DEMAND backup will be retained until customer deletes the backup or the project. The AUTOMATED backup will be retained based on the backups retention setting. | `bool` | `true` | no | | secondary\_zone | The preferred zone for the secondary/failover instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | | tier | The tier for the master instance. | `string` | `"db-n1-standard-1"` | no | | update\_timeout | The optional timout that is applied to limit long database updates. | `string` | `"30m"` | no | diff --git a/modules/safer_mysql/main.tf b/modules/safer_mysql/main.tf index d3e784cf..72398da6 100644 --- a/modules/safer_mysql/main.tf +++ b/modules/safer_mysql/main.tf @@ -50,7 +50,8 @@ module "safer_mysql" { user_labels = var.user_labels - backup_configuration = var.backup_configuration + backup_configuration = var.backup_configuration + retain_backups_on_delete = var.retain_backups_on_delete insights_config = var.insights_config diff --git a/modules/safer_mysql/variables.tf b/modules/safer_mysql/variables.tf index 33e37357..7b5ff289 100644 --- a/modules/safer_mysql/variables.tf +++ b/modules/safer_mysql/variables.tf @@ -237,6 +237,12 @@ variable "backup_configuration" { } } +variable "retain_backups_on_delete" { + description = "When this parameter is set to true, Cloud SQL retains backups of the instance even after the instance is deleted. The ON_DEMAND backup will be retained until customer deletes the backup or the project. The AUTOMATED backup will be retained based on the backups retention setting." + type = bool + default = true +} + variable "assign_public_ip" { description = "Set to true if the master instance should also have a public IP (less secure)." type = bool diff --git a/modules/safer_mysql/versions.tf b/modules/safer_mysql/versions.tf index d20bdb38..f6b4d204 100644 --- a/modules/safer_mysql/versions.tf +++ b/modules/safer_mysql/versions.tf @@ -20,7 +20,7 @@ terraform { google = { source = "hashicorp/google" - version = ">= 6.17, < 7" + version = ">= 6.31, < 7" } } From eb9b52f549b8767ab9c951abbcff2ad657ceb1dd Mon Sep 17 00:00:00 2001 From: Ben Naylor Date: Wed, 18 Jun 2025 16:50:34 +0200 Subject: [PATCH 16/17] feat: Support retain_backups_on_delete for postgres (#737) Co-authored-by: Imran Nayer --- modules/postgresql/README.md | 1 + modules/postgresql/main.tf | 1 + modules/postgresql/variables.tf | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index 11bc5066..b4b310ae 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -168,6 +168,7 @@ module "pg" { | read\_replica\_name\_suffix | The optional suffix to add to the read instance name | `string` | `""` | no | | read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null |
list(object({
name = string
name_override = optional(string)
tier = optional(string)
edition = optional(string)
availability_type = optional(string)
zone = optional(string)
disk_type = optional(string)
disk_autoresize = optional(bool)
disk_autoresize_limit = optional(number)
disk_size = optional(string)
user_labels = map(string)
database_flags = optional(list(object({
name = string
value = string
})), [])
insights_config = optional(object({
query_plans_per_minute = optional(number, 5)
query_string_length = optional(number, 1024)
record_application_tags = optional(bool, false)
record_client_address = optional(bool, false)
}), null)
ip_configuration = object({
authorized_networks = optional(list(map(string)), [])
ipv4_enabled = optional(bool)
private_network = optional(string)
ssl_mode = optional(string)
allocated_ip_range = optional(string)
enable_private_path_for_google_cloud_services = optional(bool, false)
psc_enabled = optional(bool, false)
psc_allowed_consumer_projects = optional(list(string), [])
})
encryption_key_name = optional(string)
data_cache_enabled = optional(bool)
}))
| `[]` | no | | region | The region of the Cloud SQL resources | `string` | `"us-central1"` | no | +| retain\_backups\_on\_delete | When this parameter is set to true, Cloud SQL retains backups of the instance even after the instance is deleted. The ON\_DEMAND backup will be retained until customer deletes the backup or the project. The AUTOMATED backup will be retained based on the backups retention setting. | `bool` | `false` | no | | root\_password | Initial root password during creation | `string` | `null` | no | | secondary\_zone | The preferred zone for the replica instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no | | tier | The tier for the Cloud SQL instance, for ADC its defualt value will be db-perf-optimized-N-8 which is tier value for edtion ENTERPRISE\_PLUS, if user wants to change the edition, he should chose compatible tier. | `string` | `"db-f1-micro"` | no | diff --git a/modules/postgresql/main.tf b/modules/postgresql/main.tf index a8284879..f44f7198 100644 --- a/modules/postgresql/main.tf +++ b/modules/postgresql/main.tf @@ -85,6 +85,7 @@ resource "google_sql_database_instance" "default" { connector_enforcement = local.connector_enforcement enable_google_ml_integration = var.enable_google_ml_integration enable_dataplex_integration = var.enable_dataplex_integration + retain_backups_on_delete = var.retain_backups_on_delete dynamic "backup_configuration" { for_each = local.is_secondary_instance ? [] : [var.backup_configuration] diff --git a/modules/postgresql/variables.tf b/modules/postgresql/variables.tf index 6596b0e8..3769abe2 100644 --- a/modules/postgresql/variables.tf +++ b/modules/postgresql/variables.tf @@ -477,3 +477,9 @@ variable "use_autokey" { type = bool default = false } + +variable "retain_backups_on_delete" { + description = "When this parameter is set to true, Cloud SQL retains backups of the instance even after the instance is deleted. The ON_DEMAND backup will be retained until customer deletes the backup or the project. The AUTOMATED backup will be retained based on the backups retention setting." + type = bool + default = false +} From 101c834c3cc67db5da6d2f83a052adbe85eaeaa2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:34:21 -0500 Subject: [PATCH 17/17] chore(main): release 26.0.0 (#716) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 27 +++++++++++++++++++ README.md | 2 +- examples/mssql-failover-replica/README.md | 2 +- .../README.md | 2 +- modules/mssql/README.md | 2 +- modules/mssql/metadata.yaml | 2 +- modules/mssql/versions.tf | 2 +- modules/mysql/README.md | 2 +- modules/mysql/metadata.yaml | 2 +- modules/mysql/versions.tf | 4 +-- modules/postgresql/README.md | 2 +- modules/postgresql/metadata.yaml | 2 +- modules/postgresql/versions.tf | 4 +-- modules/private_service_access/README.md | 2 +- modules/private_service_access/metadata.yaml | 2 +- modules/private_service_access/versions.tf | 4 +-- modules/safer_mysql/README.md | 2 +- modules/safer_mysql/metadata.yaml | 2 +- modules/safer_mysql/versions.tf | 2 +- 19 files changed, 48 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec233df..41d638f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [26.0.0](https://github.com/terraform-google-modules/terraform-google-sql-db/compare/v25.2.2...v26.0.0) (2025-06-18) + + +### ⚠ BREAKING CHANGES + +* **TPG>6.31:** Support retain_backups_on_delete for mysql, safer_mysql ([#735](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/735)) +* **TPG>6.17:** Adding new variables to define failover dr replica ([#728](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/728)) + +### Features + +* Add output to retrieve passwords by user name for additional_users ([#719](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/719)) ([bca69c4](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/bca69c470464d7c6211008cd5c57d11dd1f4b6ce)) +* add setting enable_dataplex_integration ([#713](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/713)) ([f5ad3e6](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/f5ad3e6e09b040928f481b4b4f7cf0c56feda9d7)) +* Add support for autokey in postgres module ([#712](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/712)) ([db53c26](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/db53c267bbba6f45d2c7f027b05d46e17f286a0c)) +* add support for server_ca_mode and custom SANs ([#714](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/714)) ([#736](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/736)) ([15e8be8](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/15e8be86f3ea98b36cb3e736c3494c1f40b30e04)) +* Remove condition from data.google_compute_zones.available ([#684](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/684)) ([af7f20c](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/af7f20c466b292a6d210a2c21c877d72d46536ea)) +* Support retain_backups_on_delete for postgres ([#737](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/737)) ([eb9b52f](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/eb9b52f549b8767ab9c951abbcff2ad657ceb1dd)) +* **TPG>6.17:** Adding new variables to define failover dr replica ([#728](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/728)) ([90a3e64](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/90a3e64bc9da13885f1fa33ed0f5a24edb1406a7)) +* **TPG>6.31:** Support retain_backups_on_delete for mysql, safer_mysql ([#735](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/735)) ([d0b31dd](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/d0b31dd44d23465df72a91d50755d1209e6c4bdc)) + + +### Bug Fixes + +* Disable SQL instance data_cache when data_cache_enabled variable is false ([#720](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/720)) ([7befe54](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/7befe54c9f4c9b38f5f6ffc4c21da8e14e387119)) +* Postgres read-replica "psc_enabled" permadiff ([923b770](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/923b7707ec468b25f4407f43d069e4124990e965)) +* replace invalid optional(string, ) with optional(string) ([#725](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/725)) ([056e436](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/056e436283f2802c8e00b3dd17390bff83f95d9b)) +* truncate service account display_name in backup module ([#734](https://github.com/terraform-google-modules/terraform-google-sql-db/issues/734)) ([edc7ee7](https://github.com/terraform-google-modules/terraform-google-sql-db/commit/edc7ee79d66658c4458a50c83e2164c0b3da0e67)) + ## [25.2.2](https://github.com/terraform-google-modules/terraform-google-sql-db/compare/v25.2.1...v25.2.2) (2025-03-05) diff --git a/README.md b/README.md index cbedc1d1..3454c1f3 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ For MySQL : ``` module "sql-db" { source = "GoogleCloudPlatform/sql-db/google//modules/mysql" - version = "~> 25.2" + version = "~> 26.0" } ``` diff --git a/examples/mssql-failover-replica/README.md b/examples/mssql-failover-replica/README.md index 050cf650..5056a20e 100644 --- a/examples/mssql-failover-replica/README.md +++ b/examples/mssql-failover-replica/README.md @@ -23,7 +23,7 @@ Promote instance 2 as primary and change instance 1 as failover replica ```diff module "mssql2" { source = "terraform-google-modules/sql-db/google//modules/mssql" - version = "~> 25.2" + version = "~> 26.0" - master_instance_name = module.mssql1.instance_name diff --git a/examples/postgresql-with-cross-region-failover/README.md b/examples/postgresql-with-cross-region-failover/README.md index 8bb982b6..15323abe 100644 --- a/examples/postgresql-with-cross-region-failover/README.md +++ b/examples/postgresql-with-cross-region-failover/README.md @@ -26,7 +26,7 @@ Promote instance 2 as primary and change instance 1 as failover replica ```diff module "pg2" { source = "terraform-google-modules/sql-db/google//modules/postgresql" - version = "~> 25.2" + version = "~> 26.0" - master_instance_name = module.pg1.instance_name diff --git a/modules/mssql/README.md b/modules/mssql/README.md index ecd25c0d..5c704eed 100644 --- a/modules/mssql/README.md +++ b/modules/mssql/README.md @@ -12,7 +12,7 @@ Basic usage of this module is as follows: ```hcl module "mssql" { source = "terraform-google-modules/sql-db/google//modules/mssql" - version = "~> 25.2" + version = "~> 26.0" name = var.name random_instance_name = true diff --git a/modules/mssql/metadata.yaml b/modules/mssql/metadata.yaml index 2bcf291b..8624a822 100644 --- a/modules/mssql/metadata.yaml +++ b/modules/mssql/metadata.yaml @@ -25,7 +25,7 @@ spec: repo: https://github.com/terraform-google-modules/terraform-google-sql-db.git sourceType: git dir: /modules/mssql - version: 25.2.2 + version: 26.0.0 actuationTool: flavor: Terraform version: ">= 1.3" diff --git a/modules/mssql/versions.tf b/modules/mssql/versions.tf index ad792fcd..998a528a 100644 --- a/modules/mssql/versions.tf +++ b/modules/mssql/versions.tf @@ -36,7 +36,7 @@ terraform { } provider_meta "google-beta" { - module_name = "blueprints/terraform/terraform-google-sql-db:mssql/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:mssql/v26.0.0" } } diff --git a/modules/mysql/README.md b/modules/mysql/README.md index 371926e0..2cafe194 100644 --- a/modules/mysql/README.md +++ b/modules/mysql/README.md @@ -10,7 +10,7 @@ Functional examples are included in the [examples](../../examples/) directory. B ```hcl module "mysql-db" { source = "terraform-google-modules/sql-db/google//modules/mysql" - version = "~> 25.2" + version = "~> 26.0" name = var.db_name random_instance_name = true diff --git a/modules/mysql/metadata.yaml b/modules/mysql/metadata.yaml index 8acaf37c..69a64fbc 100644 --- a/modules/mysql/metadata.yaml +++ b/modules/mysql/metadata.yaml @@ -25,7 +25,7 @@ spec: repo: https://github.com/terraform-google-modules/terraform-google-sql-db.git sourceType: git dir: /modules/mysql - version: 25.2.2 + version: 26.0.0 actuationTool: flavor: Terraform version: ">= 1.3" diff --git a/modules/mysql/versions.tf b/modules/mysql/versions.tf index fd61ed03..1a5d5ea3 100644 --- a/modules/mysql/versions.tf +++ b/modules/mysql/versions.tf @@ -36,10 +36,10 @@ terraform { } provider_meta "google" { - module_name = "blueprints/terraform/terraform-google-sql-db:mysql/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:mysql/v26.0.0" } provider_meta "google-beta" { - module_name = "blueprints/terraform/terraform-google-sql-db:mysql/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:mysql/v26.0.0" } } diff --git a/modules/postgresql/README.md b/modules/postgresql/README.md index b4b310ae..4d3c406d 100644 --- a/modules/postgresql/README.md +++ b/modules/postgresql/README.md @@ -13,7 +13,7 @@ Basic usage of this module is as follows: ```hcl module "pg" { source = "terraform-google-modules/sql-db/google//modules/postgresql" - version = "~> 25.2" + version = "~> 26.0" name = var.pg_ha_name random_instance_name = true diff --git a/modules/postgresql/metadata.yaml b/modules/postgresql/metadata.yaml index a9bd516c..8ffeea00 100644 --- a/modules/postgresql/metadata.yaml +++ b/modules/postgresql/metadata.yaml @@ -25,7 +25,7 @@ spec: repo: https://github.com/terraform-google-modules/terraform-google-sql-db.git sourceType: git dir: /modules/postgresql - version: 25.2.2 + version: 26.0.0 actuationTool: flavor: Terraform version: ">= 1.3" diff --git a/modules/postgresql/versions.tf b/modules/postgresql/versions.tf index c0e950d1..bb6d1c78 100644 --- a/modules/postgresql/versions.tf +++ b/modules/postgresql/versions.tf @@ -36,10 +36,10 @@ terraform { } provider_meta "google" { - module_name = "blueprints/terraform/terraform-google-sql-db:postgresql/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:postgresql/v26.0.0" } provider_meta "google-beta" { - module_name = "blueprints/terraform/terraform-google-sql-db:postgresql/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:postgresql/v26.0.0" } } diff --git a/modules/private_service_access/README.md b/modules/private_service_access/README.md index abb0bcd0..610e5d24 100644 --- a/modules/private_service_access/README.md +++ b/modules/private_service_access/README.md @@ -16,7 +16,7 @@ Basic usage of this module is as follows: ``` module "test_psa" { source = "terraform-google-modules/sql-db/google//modules/private_service_access" - version = "~> 25.2" + version = "~> 26.0" project_id = var.project_id vpc_network = google_compute_network.default.name diff --git a/modules/private_service_access/metadata.yaml b/modules/private_service_access/metadata.yaml index 9113c409..37980a14 100644 --- a/modules/private_service_access/metadata.yaml +++ b/modules/private_service_access/metadata.yaml @@ -25,7 +25,7 @@ spec: repo: https://github.com/terraform-google-modules/terraform-google-sql-db.git sourceType: git dir: /modules/private_service_access - version: 25.2.2 + version: 26.0.0 actuationTool: flavor: Terraform version: ">= 0.13" diff --git a/modules/private_service_access/versions.tf b/modules/private_service_access/versions.tf index 8a0441dd..02bd2fa2 100644 --- a/modules/private_service_access/versions.tf +++ b/modules/private_service_access/versions.tf @@ -32,11 +32,11 @@ terraform { } provider_meta "google" { - module_name = "blueprints/terraform/terraform-google-sql-db:private_service_access/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:private_service_access/v26.0.0" } provider_meta "google-beta" { - module_name = "blueprints/terraform/terraform-google-sql-db:private_service_access/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:private_service_access/v26.0.0" } } diff --git a/modules/safer_mysql/README.md b/modules/safer_mysql/README.md index c0b9de04..32a7ba72 100644 --- a/modules/safer_mysql/README.md +++ b/modules/safer_mysql/README.md @@ -167,7 +167,7 @@ Functional examples are included in the [examples](../../examples/) directory. B ```hcl module "safer-mysql-db" { source = "terraform-google-modules/sql-db/google//modules/safer_mysql" - version = "~> 25.2" + version = "~> 26.0" name = var.db_name diff --git a/modules/safer_mysql/metadata.yaml b/modules/safer_mysql/metadata.yaml index 26e0b6e5..fe6bdcef 100644 --- a/modules/safer_mysql/metadata.yaml +++ b/modules/safer_mysql/metadata.yaml @@ -25,7 +25,7 @@ spec: repo: https://github.com/terraform-google-modules/terraform-google-sql-db.git sourceType: git dir: /modules/safer_mysql - version: 25.2.2 + version: 26.0.0 actuationTool: flavor: Terraform version: ">= 1.3" diff --git a/modules/safer_mysql/versions.tf b/modules/safer_mysql/versions.tf index f6b4d204..a5b415c9 100644 --- a/modules/safer_mysql/versions.tf +++ b/modules/safer_mysql/versions.tf @@ -25,7 +25,7 @@ terraform { } provider_meta "google" { - module_name = "blueprints/terraform/terraform-google-sql-db:safer_mysql/v25.2.2" + module_name = "blueprints/terraform/terraform-google-sql-db:safer_mysql/v26.0.0" } }