-
Notifications
You must be signed in to change notification settings - Fork 463
Description
TL;DR
Bug Description
The PostgreSQL module's read replica configuration has an inconsistency in how it handles zone fallbacks. While local.zone
is properly defined with a fallback mechanism, the region
and encryption_key_name
calculations still reference var.zone
directly, which can cause Terraform errors when var.zone
is null.
Affected file
Root Cause
The code defines local.zone
with proper fallback logic:
locals {
zone = var.zone == null ? data.google_compute_zones.available.names[0] : var.zone
}
Expected behavior
When var.zone
is null:
The replica should automatically use the first available zone in the region (as defined in local.zone)
The region calculation should work correctly by extracting the region from the fallback zone
The encryption_key_name logic should properly determine cross-region vs same-region replicas
No Terraform errors should occur during planning or applying
Observed behavior
When var.zone
is not specified (null), the following lines fail:
- Line 36:
region = join("-", slice(split("-", lookup(each.value, "zone", var.zone)), 0, 2))
- Line 39:
encryption_key_name = (join("-", slice(split("-", lookup(each.value, "zone", var.zone)), 0, 2))) == var.region ? null : each.value.encryption_key_name
This results in a Terraform error:
╷
│ Error: Invalid function argument
│
│ on .terraform/modules/pg.this.cloud_psql/modules/postgresql/read_replica.tf line 40, in resource "google_sql_database_instance" "replicas":
│ 40: encryption_key_name = (join("-", slice(split("-", lookup(each.value, "zone", var.zone)), 0, 2))) == var.region ? null : each.value.encryption_key_name
│ ├────────────────
│ │ while calling split(separator, str)
│ │ each.value is object with 16 attributes
│ │ var.zone is null
│
│ Invalid value for "str" parameter: argument must not be null.
╵
Terraform Configuration
# Reproducible Terraform configuration that demonstrates the issue
terraform {
required_version = ">= 1.3"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 5.0"
}
}
}
provider "google" {
project = "your-project-id"
region = "us-central1"
}
provider "google-beta" {
project = "your-project-id"
region = "us-central1"
}
# VPC network for private IP
resource "google_compute_network" "vpc" {
name = "test-vpc"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "subnet" {
name = "test-subnet"
ip_cidr_range = "10.0.0.0/24"
region = "us-central1"
network = google_compute_network.vpc.id
}
# Private services access
resource "google_compute_global_address" "private_ip_range" {
name = "test-private-ip"
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = google_compute_network.vpc.id
}
resource "google_service_networking_connection" "private_vpc_connection" {
network = google_compute_network.vpc.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.private_ip_range.name]
}
# PostgreSQL module configuration that triggers the bug
module "postgresql" {
source = "GoogleCloudPlatform/sql-db/google//modules/postgresql"
version = "~> 21.0"
name = "test-postgres"
database_version = "POSTGRES_15"
project_id = "your-project-id"
region = "us-central1"
# Critical: zone is NOT specified (null) - this triggers the bug
zone = null
tier = "db-f1-micro"
ip_configuration = {
ipv4_enabled = false
private_network = google_compute_network.vpc.id
allocated_ip_range = google_compute_global_address.private_ip_range.name
enable_private_path_for_google_cloud_services = true
}
# Read replicas configuration - this is where the bug manifests
read_replicas = [
{
name = "replica1"
# Zone not specified for replica either - relies on fallback
tier = "db-f1-micro"
ip_configuration = {
ipv4_enabled = false
private_network = google_compute_network.vpc.id
allocated_ip_range = google_compute_global_address.private_ip_range.name
enable_private_path_for_google_cloud_services = true
}
},
{
name = "replica2"
# Cross-region replica to test encryption_key_name logic
zone = "us-west1-a"
tier = "db-f1-micro"
encryption_key_name = "projects/your-project-id/locations/us-west1/keyRings/test-ring/cryptoKeys/test-key"
ip_configuration = {
ipv4_enabled = false
private_network = google_compute_network.vpc.id
allocated_ip_range = google_compute_global_address.private_ip_range.name
enable_private_path_for_google_cloud_services = true
}
}
]
depends_on = [google_service_networking_connection.private_vpc_connection]
}
Terraform Version
Terraform v1.12.0
on darwin_arm64
+ provider registry.terraform.io/cyrilgdn/postgresql v1.25.0
+ provider registry.terraform.io/hashicorp/google v6.47.0
+ provider registry.terraform.io/hashicorp/google-beta v6.47.0
+ provider registry.terraform.io/hashicorp/helm v3.0.2
+ provider registry.terraform.io/hashicorp/kubernetes v2.38.0
+ provider registry.terraform.io/hashicorp/null v3.2.4
+ provider registry.terraform.io/hashicorp/random v3.7.2
+ provider registry.terraform.io/hashicorp/time v0.13.1
Terraform Provider Versions
Providers required by configuration:
.
└── module.pg
└── module.this
├── provider[registry.terraform.io/cyrilgdn/postgresql] 1.25.0
├── 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/random]
├── module.psc_consumer_replicas
│ └── module.raw_psc_consumer
│ └── provider[registry.terraform.io/hashicorp/google]
├── module.cloud_psql
│ ├── 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
├── module.cloudsql_autorestore
│ ├── provider[registry.terraform.io/hashicorp/helm] >= 3.0.2
│ ├── provider[registry.terraform.io/hashicorp/kubernetes] >= 2.0.0
│ ├── provider[registry.terraform.io/hashicorp/google]
│ └── provider[registry.terraform.io/hashicorp/random]
├── module.csql_migration
│ └── provider[registry.terraform.io/hashicorp/google]
├── module.database
│ ├── provider[registry.terraform.io/cyrilgdn/postgresql] 1.25.0
│ └── provider[registry.terraform.io/hashicorp/google] >= 6.1.0, < 7.0.0
├── module.init_passwords
│ ├── provider[registry.terraform.io/hashicorp/google] >= 6.1.0, < 7.0.0
│ └── provider[registry.terraform.io/hashicorp/random]
├── module.project
│ ├── provider[registry.terraform.io/hashicorp/google]
│ ├── provider[registry.terraform.io/hashicorp/time]
│ ├── provider[registry.terraform.io/hashicorp/random]
│ ├── module.folder_iam
│ ├── provider[registry.terraform.io/hashicorp/google] >= 3.53.0, < 7.0.0
│ └── module.helper
│ └── module.owner_folder_iam
│ ├── provider[registry.terraform.io/hashicorp/google] >= 3.53.0, < 7.0.0
│ └── module.helper
└── module.psc_consumer
└── module.raw_psc_consumer
└── provider[registry.terraform.io/hashicorp/google]
Providers required by state:
provider[registry.terraform.io/hashicorp/kubernetes]
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]
provider[registry.terraform.io/hashicorp/time]
Additional information
No response