diff --git a/modules/alloydb/README.md b/modules/alloydb/README.md index b8d286eafd..81bc884434 100644 --- a/modules/alloydb/README.md +++ b/modules/alloydb/README.md @@ -257,31 +257,31 @@ module "alloydb" { | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [cluster_name](variables.tf#L99) | Name of the primary cluster. | string | ✓ | | -| [instance_name](variables.tf#L184) | Name of primary instance. | string | ✓ | | -| [location](variables.tf#L195) | Region or zone of the cluster and instance. | string | ✓ | | -| [network_config](variables.tf#L251) | Network configuration for cluster and instance. Only one between psa_config and psc_config can be used. | object({…}) | ✓ | | -| [project_id](variables.tf#L294) | The ID of the project where this instances will be created. | string | ✓ | | +| [instance_name](variables.tf#L192) | Name of primary instance. | string | ✓ | | +| [location](variables.tf#L203) | Region or zone of the cluster and instance. | string | ✓ | | +| [network_config](variables.tf#L259) | Network configuration for cluster and instance. Only one between psa_config and psc_config can be used. | object({…}) | ✓ | | +| [project_id](variables.tf#L302) | The ID of the project where this instances will be created. | string | ✓ | | | [annotations](variables.tf#L17) | Map FLAG_NAME=>VALUE for annotations which allow client tools to store small amount of arbitrary data. | map(string) | | null | | [automated_backup_configuration](variables.tf#L23) | Automated backup settings for cluster. | object({…}) | | {…} | | [availability_type](variables.tf#L76) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | string | | "REGIONAL" | | [client_connection_config](variables.tf#L82) | Client connection config. | object({…}) | | null | | [cluster_display_name](variables.tf#L93) | Display name of the primary cluster. | string | | null | | [continuous_backup_configuration](variables.tf#L104) | Continuous backup settings for cluster. | object({…}) | | {…} | -| [cross_region_replication](variables.tf#L117) | Cross region replication config. | object({…}) | | {} | -| [database_version](variables.tf#L135) | Database type and version to create. | string | | "POSTGRES_15" | -| [deletion_policy](variables.tf#L141) | AlloyDB cluster and instance deletion policy. | string | | null | -| [display_name](variables.tf#L147) | AlloyDB instance display name. | string | | null | -| [encryption_config](variables.tf#L153) | Set encryption configuration. KMS name format: 'projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]'. | object({…}) | | null | -| [flags](variables.tf#L163) | Map FLAG_NAME=>VALUE for database-specific tuning. | map(string) | | null | -| [gce_zone](variables.tf#L169) | The GCE zone that the instance should serve from. This can ONLY be specified for ZONAL instances. If present for a REGIONAL instance, an error will be thrown. | string | | null | -| [initial_user](variables.tf#L175) | AlloyDB cluster initial user credentials. | object({…}) | | null | -| [labels](variables.tf#L189) | Labels to be attached to all instances. | map(string) | | null | -| [machine_config](variables.tf#L200) | AlloyDB machine config. | object({…}) | | {…} | -| [maintenance_config](variables.tf#L211) | Set maintenance window configuration. | object({…}) | | {…} | -| [prefix](variables.tf#L284) | Optional prefix used to generate instance names. | string | | null | -| [query_insights_config](variables.tf#L299) | Query insights config. | object({…}) | | {…} | -| [tag_bindings](variables.tf#L315) | Tag bindings for this service, in key => tag value id format. | map(string) | | {} | -| [users](variables.tf#L322) | Map of users to create in the primary instance (and replicated to other replicas). Set PASSWORD to null if you want to get an autogenerated password. The user types available are: 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'. | map(object({…})) | | null | +| [cross_region_replication](variables.tf#L117) | Cross region replication config. | object({…}) | | {} | +| [database_version](variables.tf#L143) | Database type and version to create. | string | | "POSTGRES_15" | +| [deletion_policy](variables.tf#L149) | AlloyDB cluster and instance deletion policy. | string | | null | +| [display_name](variables.tf#L155) | AlloyDB instance display name. | string | | null | +| [encryption_config](variables.tf#L161) | Set encryption configuration. KMS name format: 'projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]'. | object({…}) | | null | +| [flags](variables.tf#L171) | Map FLAG_NAME=>VALUE for database-specific tuning. | map(string) | | null | +| [gce_zone](variables.tf#L177) | The GCE zone that the instance should serve from. This can ONLY be specified for ZONAL instances. If present for a REGIONAL instance, an error will be thrown. | string | | null | +| [initial_user](variables.tf#L183) | AlloyDB cluster initial user credentials. | object({…}) | | null | +| [labels](variables.tf#L197) | Labels to be attached to all instances. | map(string) | | null | +| [machine_config](variables.tf#L208) | AlloyDB machine config. | object({…}) | | {…} | +| [maintenance_config](variables.tf#L219) | Set maintenance window configuration. | object({…}) | | {…} | +| [prefix](variables.tf#L292) | Optional prefix used to generate instance names. | string | | null | +| [query_insights_config](variables.tf#L307) | Query insights config. | object({…}) | | {…} | +| [tag_bindings](variables.tf#L323) | Tag bindings for this service, in key => tag value id format. | map(string) | | {} | +| [users](variables.tf#L330) | Map of users to create in the primary instance (and replicated to other replicas). Set PASSWORD to null if you want to get an autogenerated password. The user types available are: 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'. | map(object({…})) | | null | ## Outputs diff --git a/modules/alloydb/main.tf b/modules/alloydb/main.tf index e538eb8180..57ae887324 100644 --- a/modules/alloydb/main.tf +++ b/modules/alloydb/main.tf @@ -43,7 +43,7 @@ resource "google_alloydb_cluster" "primary" { project = var.project_id annotations = var.annotations cluster_id = local.primary_cluster_name - cluster_type = "PRIMARY" + cluster_type = var.cross_region_replication.switchover_mode ? "SECONDARY" : "PRIMARY" database_version = var.database_version deletion_policy = var.deletion_policy display_name = coalesce(var.cluster_display_name, local.primary_cluster_name) @@ -144,6 +144,13 @@ resource "google_alloydb_cluster" "primary" { psc_enabled = var.network_config.psc_config != null ? true : null } + dynamic "secondary_config" { + for_each = var.cross_region_replication.switchover_mode ? [""] : [] + content { + primary_cluster_name = "projects/${var.project_id}/locations/${var.cross_region_replication.region}/clusters/${local.secondary_cluster_name}" + } + } + # waiting to fix this issue https://github.com/hashicorp/terraform-provider-google/issues/14944 lifecycle { ignore_changes = [ @@ -161,7 +168,7 @@ resource "google_alloydb_instance" "primary" { database_flags = var.flags display_name = coalesce(var.display_name, local.primary_instance_name) instance_id = local.primary_instance_name - instance_type = "PRIMARY" + instance_type = var.cross_region_replication.switchover_mode ? "SECONDARY" : "PRIMARY" gce_zone = local.is_regional ? null : var.gce_zone labels = var.labels @@ -228,7 +235,7 @@ resource "google_alloydb_cluster" "secondary" { project = var.project_id annotations = var.annotations cluster_id = local.secondary_cluster_name - cluster_type = var.cross_region_replication.promote_secondary ? "PRIMARY" : "SECONDARY" + cluster_type = var.cross_region_replication.promote_secondary || var.cross_region_replication.switchover_mode ? "PRIMARY" : "SECONDARY" database_version = var.database_version deletion_policy = "FORCE" display_name = coalesce(var.cross_region_replication.secondary_cluster_display_name, local.secondary_cluster_name) @@ -322,7 +329,7 @@ resource "google_alloydb_cluster" "secondary" { } dynamic "secondary_config" { - for_each = var.cross_region_replication.promote_secondary ? [] : [""] + for_each = var.cross_region_replication.promote_secondary || var.cross_region_replication.switchover_mode ? [] : [""] content { primary_cluster_name = google_alloydb_cluster.primary.id } @@ -365,9 +372,9 @@ resource "google_alloydb_instance" "secondary" { } dynamic "machine_config" { - for_each = var.machine_config != null ? [""] : [] + for_each = var.machine_config != null || var.cross_region_replication.secondary_machine_config != null ? [""] : [] content { - cpu_count = var.machine_config.cpu_count + cpu_count = coalesce(try(var.machine_config.cpu_count, null), try(var.cross_region_replication.secondary_machine_config.cpu_count, null)) } } diff --git a/modules/alloydb/tags.tf b/modules/alloydb/tags.tf index c37a9f1be3..0378c93d4e 100644 --- a/modules/alloydb/tags.tf +++ b/modules/alloydb/tags.tf @@ -14,10 +14,14 @@ * limitations under the License. */ +data "google_project" "project" { + project_id = var.project_id +} + resource "google_tags_location_tag_binding" "primary_binding" { for_each = var.tag_bindings parent = ( - "//alloydb.googleapis.com/${google_alloydb_cluster.primary.id}" + "//alloydb.googleapis.com/projects/${data.google_project.project.number}/locations/${var.location}/clusters/${google_alloydb_cluster.primary.cluster_id}" ) tag_value = each.value location = var.location @@ -26,9 +30,8 @@ resource "google_tags_location_tag_binding" "primary_binding" { resource "google_tags_location_tag_binding" "secondary_binding" { for_each = var.cross_region_replication.enabled ? var.tag_bindings : {} parent = ( - "//alloydb.googleapis.com/${google_alloydb_cluster.secondary[0].id}" + "//alloydb.googleapis.com/projects/${data.google_project.project.number}/locations/${var.cross_region_replication.region}/clusters/${google_alloydb_cluster.secondary[0].cluster_id}" ) tag_value = each.value location = var.cross_region_replication.region } - diff --git a/modules/alloydb/variables.tf b/modules/alloydb/variables.tf index 11771f00da..a8dd524e5a 100644 --- a/modules/alloydb/variables.tf +++ b/modules/alloydb/variables.tf @@ -119,17 +119,25 @@ variable "cross_region_replication" { type = object({ enabled = optional(bool, false) promote_secondary = optional(bool, false) + switchover_mode = optional(bool, false) region = optional(string, null) secondary_cluster_display_name = optional(string, null) secondary_cluster_name = optional(string, null) secondary_instance_display_name = optional(string, null) secondary_instance_name = optional(string, null) + secondary_machine_config = optional(object({ + cpu_count = number + }), null) }) default = {} validation { condition = !var.cross_region_replication.enabled || var.cross_region_replication.enabled && var.cross_region_replication.region != null error_message = "Region must be available when cross region replication is enabled." } + validation { + condition = !(var.cross_region_replication.switchover_mode && var.cross_region_replication.promote_secondary) + error_message = "Please choose to either promote secondary cluster or align an existing cluster after swtichover." + } } variable "database_version" {