-
Notifications
You must be signed in to change notification settings - Fork 459
Description
TL;DR
I am using a combination of GoogleCloudPlatform/sql-db/google//modules/mysql
and GoogleCloudPlatform/sql-db/google//modules/backup
to create a MySQL database and setup GCS bucket exports.
I have ran into a scenario where the data "google_sql_database_instance" "backup_instance"
data source inside the GoogleCloudPlatform/sql-db/google//modules/backup
module references the database instance that has not yet been created, meaning the plan always fails.
Expected behavior
The modules/backup
should depend on modules/mysql
such that the instance resource has been created before the backups module tries to reference it.
Observed behavior
My plan includes the creation of the database instance (by modules/mysql
), but then fails to plan the modules/backup
part, as the instance doesn't exist at plan time...
module.mysql.google_sql_database_instance.default will be created
+ resource "google_sql_database_instance" "default" {
+ database_version = "MYSQL_8_0_40"
+ ip_address = (known after apply)
+ name = "foo-bar-baz-0e64d9b9"
....
}
Plan: 32 to add, 0 to change, 0 to destroy.
╷
│ Error: foo-bar-baz-0e64d9b9 not found
│
│ with module.cloudsql_backup.data.google_sql_database_instance.backup_instance,
│ on .terraform/modules/cloudsql_backup/modules/backup/main.tf line 69, in data "google_sql_database_instance" "backup_instance":
│ 69: data "google_sql_database_instance" "backup_instance" {
What is so strange about this situation is that the sql_instance
name passed to the backup
module is module.mysql.instance_name
, so terraform should know that the backup module resource creation is dependent on the mysql module.
To provide some additional context about the lead-up to this situation...
- I tried to
terraform apply
, but the apply failed to create the database instance due to a misconfiguration (missing allocated IP range):module.mysql.random_id.suffix[0]: Creating... module.mysql.null_resource.module_depends_on: Creating... module.mysql.null_resource.module_depends_on: Creation complete after 0s [id=1199820259109330906] module.mysql.random_id.suffix[0]: Creation complete after 0s [id=C2XYuA] module.mysql.google_sql_database_instance.default: Creating... Error: Error, failed to create instance foo-bar-baz-0e64d9b9: googleapi: Error 400: Invalid request: Incorrect Service Networking. config for instance: ************:foo-bar-baz-0e64d9b9: Reserved range [[**********]] not found in consumer project:********., invalid with module.mysql.google_sql_database_instance.default, on .terraform/modules/mysql/modules/mysql/main.tf line 54, in resource "google_sql_database_instance" "default": 54: resource "google_sql_database_instance" "default" {
- I fixed the misconfiguration and tried to re-run the plan, but now get the above error even trying to run the plan.
Hypothesis
I have a hypothesis about what the cause is.
In the mysql
module, the database name is created from the name
and random_id.suffix
values in main.tf
:
locals {
master_instance_name = var.random_instance_name ? "${var.name}-${random_id.suffix[0].hex}" : var.name
...
}
resource "google_sql_database_instance" "default" {
provider = google-beta
project = var.project_id
name = local.master_instance_name
...
}
Then in outputs.tf
this value is exported, which I reference.
output "instance_name" {
value = google_sql_database_instance.default.name
description = "The instance name for the master instance"
}
Is it possible that since the var.name
is known, andrandom_id.suffix
resource already got created (module.mysql.random_id.suffix[0]: Creating...
), that Terraform is short-circuiting the creation of the google_sql_database_instance
, and therefore the instance_name
output can be used before the database exists?
Therefore it is possible for me to be in a situation where the "instance_name" output refers to an instance that does not exist.
Terraform Configuration
module "mysql" {
source = "GoogleCloudPlatform/sql-db/google//modules/mysql"
version = "24.0.1"
project_id = var.project_id
instance_type = "CLOUD_SQL_INSTANCE"
database_version = "MYSQL_8_0_40"
deletion_protection = var.db_config.deletion_protection
deletion_protection_enabled = var.db_config.deletion_protection
disk_autoresize = true
disk_size = 10
name = local.database_name
user_name = "*********"
user_password = var.*********_db_password
user_host = null
additional_users = var.additional_users
iam_users = local.iam_users
zone = "*********"
region = "*********"
tier = var.db_config.tier
edition = var.db_config.edition
enable_default_db = false
maintenance_window_day = 6
maintenance_window_hour = 23
maintenance_window_update_track = var.db_config.maintenance_window_update_track
random_instance_name = true
data_cache_enabled = false
ip_configuration = {
ipv4_enabled = false
authorized_networks = []
ssl_mode = "TRUSTED_CLIENT_CERTIFICATE_REQUIRED"
private_network = data.google_compute_network.network.id
allocated_ip_range = var.db_config.allocated_ip_range
psc_enabled = var.db_config.psc_enabled
psc_allowed_consumer_projects = var.db_config.psc_allowed_consumer_projects
}
backup_configuration = {
enabled = true
location = "eu"
binary_log_enabled = true
retained_backups = 14
retention_unit = "COUNT"
start_time = "00:00"
transaction_log_retention_days = 7
}
insights_config = {
query_plans_per_minute = 5 # default
query_string_length = 1024 # default
record_application_tags = false # default
record_client_address = false # "Insights record client address is not supported for instances with PSC connectivity enabled"
}
database_flags = local.db_flags
}
module "cloudsql_backup" {
source = "GoogleCloudPlatform/sql-db/google//modules/backup"
version = "24.0.1"
export_databases = [] // exports all databases
enable_export_backup = true
enable_internal_backup = false // covered by mysql module
export_schedule = "0 0 * * *" // at midnight
export_uri = google_storage_bucket.*******_export_bucket.url
region = "*******"
project_id = var.project_id
sql_instance = module.mysql.instance_name
deletion_protection = var.backup_deletion_protection
}
Terraform Version
$ terraform version
Terraform v1.10.1
Terraform Provider Versions
terraform providers
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/google]
├── module.primary
│ ├── provider[registry.terraform.io/hashicorp/google]
│ ├── provider[registry.terraform.io/hashicorp/random]
│ ├── module.cloudsql_backup
│ │ └── provider[registry.terraform.io/hashicorp/google] >= 6.11.0, < 7.0.0
│ └── module.mysql
│ ├── provider[registry.terraform.io/hashicorp/google-beta] >= 6.1.0, < 7.0.0
│ ├── provider[registry.terraform.io/hashicorp/null] ~> 3.1
│ ├── provider[registry.terraform.io/hashicorp/random] ~> 3.1
│ └── provider[registry.terraform.io/hashicorp/google] >= 6.1.0, < 7.0.0
└── module.failover
├── provider[registry.terraform.io/hashicorp/google]
├── provider[registry.terraform.io/hashicorp/random]
├── module.cloudsql_backup
└── provider[registry.terraform.io/hashicorp/google] >= 6.11.0, < 7.0.0
└── module.mysql
├── provider[registry.terraform.io/hashicorp/google] >= 6.1.0, < 7.0.0
├── provider[registry.terraform.io/hashicorp/google-beta] >= 6.1.0, < 7.0.0
├── provider[registry.terraform.io/hashicorp/null] ~> 3.1
└── provider[registry.terraform.io/hashicorp/random] ~> 3.1
Providers required by state:
provider[registry.terraform.io/hashicorp/google]
provider[registry.terraform.io/hashicorp/google-beta]
provider[registry.terraform.io/hashicorp/null]
provider[registry.terraform.io/hashicorp/random]
Additional information
No response