diff --git a/cloud/aws/rds_serverless/debug.tf b/cloud/aws/rds_serverless/debug.tf index 7a285f2..fdd17f0 100644 --- a/cloud/aws/rds_serverless/debug.tf +++ b/cloud/aws/rds_serverless/debug.tf @@ -1,27 +1,64 @@ resource "local_file" "debug" { content = nonsensitive(jsonencode({ rds = { - instance_name = var.instance_name, - tennants = var.tenants, - application_arn = try(var.application.arn, null), - application_name = try(var.application.name, null), - engine_user = var.engine, - engine_actual = data.aws_rds_engine_version.latest[var.engine_version].engine - engine_version_actual = data.aws_rds_engine_version.latest[var.engine_version].version, - endpoints = { - write = aws_rds_cluster_endpoint.endpoint["write"].endpoint, - read = aws_rds_cluster_endpoint.endpoint["read"].endpoint + instance_name = var.instance_name, + tennants = var.tenants, + application_arn = try(var.application.arn, null), + application_name = try(var.application.name, null), + engine = { + requested = { + engine = var.engine, + version = var.engine_version + } + resolved = { + engine = data.aws_rds_engine_version.latest[var.engine_version].engine, + version = data.aws_rds_engine_version.latest[var.engine_version].version, + match = data.aws_rds_engine_version.latest, + } } + #endpoints = { + # write = aws_rds_cluster_endpoint.endpoint["write"].endpoint, + # read = aws_rds_cluster_endpoint.endpoint["read"].endpoint + #} admin = { username = local.admin_username password = local.admin_password } } - tenants = { - input = var.tenants - output = local.output_tenants - } + tenants = var.tenants })) - filename = "${path.root}/.debug/aws/rds/serverless/${var.instance_name}.json" + filename = "${path.root}/.debug/aws/rds/serverless/${var.instance_name}.provided.json" + file_permission = "0600" +} +resource "local_file" "debug_result" { + content = nonsensitive(jsonencode({ + rds = { + instance_name = var.instance_name, + tennants = var.tenants, + application_arn = try(var.application.arn, null), + application_name = try(var.application.name, null), + engine = { + requested = { + engine = var.engine, + version = var.engine_version + } + resolved = { + engine = data.aws_rds_engine_version.latest[var.engine_version].engine, + version = data.aws_rds_engine_version.latest[var.engine_version].version, + match = data.aws_rds_engine_version.latest[var.engine_version], + } + } + endpoints = { + write = aws_rds_cluster_endpoint.endpoint["write"].endpoint, + read = aws_rds_cluster_endpoint.endpoint["read"].endpoint + } + } + tenants = merge({ admin = { + username = local.admin_username + password = local.admin_password + } }, local.output_tenants) + + })) + filename = "${path.root}/.debug/aws/rds/serverless/${var.instance_name}.result.json" file_permission = "0600" } \ No newline at end of file diff --git a/cloud/aws/rds_serverless/inputs.tf b/cloud/aws/rds_serverless/inputs.tf index 2d6cbc3..209ff33 100644 --- a/cloud/aws/rds_serverless/inputs.tf +++ b/cloud/aws/rds_serverless/inputs.tf @@ -5,8 +5,6 @@ variable "instance_name" { } locals { sanitised_name = lower(replace(var.instance_name, "[^a-zA-Z0-9]", "-")) - titled_name = replace(title(join(" ", split("-", local.sanitised_name))), " ", "") - app_name = try(var.application.name, local.titled_name) } variable "tenants" { type = map(object({ @@ -26,24 +24,56 @@ variable "application" { }) default = null } -variable "aws_profile" { - type = string - description = "AWS profile to use for generating RDS auth token" - default = null -} variable "engine" { type = string - description = "The database engine to use" + description = "The database engine to use. This must be either aurora-mysql or aurora-postgresql" default = "aurora-mysql" validation { error_message = "Must be either aurora-mysql or aurora-postgresql" condition = contains(["aurora-mysql", "aurora-postgresql"], var.engine) } } +locals { + is_mysql = var.engine == "aurora-mysql" + is_postgres = var.engine == "aurora-postgresql" + supported_mysql = ["5.7", "8.0"] + supported_postgres = [ + "11.9", "11.21", + "12.9", "12.11", "12.12", "12.13", "12.14", "12.15", "12.16", "12.17", "12.18", "12.19", "12.20", "12.22", + "13.7", "13.8", "13.9", "13.10", "13.11", "13.12", "13.12", "13.13", "13.14", "13.15", "13.16", "13.18", + "14.3", "14.4", "14.5", "14.6", "14.7", "14.8", "14.9", "14.10", "14.11", "14.12", "14.13", "14.15", + "15.2", "15.3", "15.4", "15.5", "15.6", "15.7", "15.8", "15.10", + "16.1", "16.2", "16.3", "16.4", "16.6", + ] + engines_supporting_local_write_forwarding ={ + "aurora-mysql" = ["8.0"] + "aurora-postgresql" = [ + "14.13", "14.15", + "15.8", "15.10", + "16.4", "16.6", + ] + } + # MB: This is a hack until I get my patch into terraform's aws provider: https://github.com/hashicorp/terraform-provider-aws/pull/40700 + supports_local_write_forwarding = ( + local.is_mysql && contains(local.engines_supporting_local_write_forwarding.aurora-mysql, local.engine_version)|| + local.is_postgres && contains(local.engines_supporting_local_write_forwarding.aurora-postgresql, local.engine_version) + ) +} variable "engine_version" { type = string - default = "8.0" + default = null + validation { + error_message = "If the engine is mysql_aurora, the engine_version must be one of ${join(", ", local.supported_mysql)}." + condition = local.is_mysql ? contains(local.supported_mysql, var.engine_version) : true + } + validation { + error_message = "If the engine is aurora-postgresql, the engine_version must be one of ${join(", ", local.supported_postgres)}." + condition = local.is_postgres ? contains(local.supported_postgres, var.engine_version) : true + } +} +locals { + engine_version = var.engine_version != null ? var.engine_version : "8.0" } variable "scaling" { @@ -69,6 +99,12 @@ variable "scaling" { } } +locals { + scaling = merge(var.scaling, { + min_capacity = local.is_mysql && var.engine_version == "5.7" && var.scaling.min_capacity == 0 ? 1 : var.scaling.min_capacity + }) +} + variable "backup_window" { type = string description = "The daily time range during which automated backups are created if automated backups are enabled." diff --git a/cloud/aws/rds_serverless/rds.tf b/cloud/aws/rds_serverless/rds.tf index 9f62d33..b74e8a2 100644 --- a/cloud/aws/rds_serverless/rds.tf +++ b/cloud/aws/rds_serverless/rds.tf @@ -30,7 +30,7 @@ resource "aws_rds_cluster" "cluster" { master_username = local.admin_username master_password = local.admin_password storage_encrypted = true - enable_local_write_forwarding = true + enable_local_write_forwarding = local.supports_local_write_forwarding backup_retention_period = var.backup_retention_period_days skip_final_snapshot = var.skip_final_snapshot preferred_backup_window = var.backup_window @@ -41,13 +41,16 @@ resource "aws_rds_cluster" "cluster" { vpc_security_group_ids = [aws_security_group.rds.id] serverlessv2_scaling_configuration { - max_capacity = var.scaling.max_capacity - min_capacity = var.scaling.min_capacity + max_capacity = local.scaling.max_capacity + min_capacity = local.scaling.min_capacity } lifecycle { create_before_destroy = false - replace_triggered_by = [data.aws_rds_engine_version.latest] + precondition { + error_message = "If you're using mysql 5.7, min_capacity must be greater or equal to 1, because it doesn't support auto-pause." + condition = local.is_mysql && var.engine_version == "5.7" ? local.scaling.min_capacity >= 1 : true + } } tags = merge( @@ -56,7 +59,6 @@ resource "aws_rds_cluster" "cluster" { Name = var.instance_name } ) - } data "aws_rds_certificate" "default" { diff --git a/cloud/aws/rds_serverless/tenant/db.tf b/cloud/aws/rds_serverless/tenant/db.tf index edf7de9..745cfa7 100644 --- a/cloud/aws/rds_serverless/tenant/db.tf +++ b/cloud/aws/rds_serverless/tenant/db.tf @@ -1,5 +1,4 @@ locals { - is_mysql = var.engine == "aurora-mysql" db_tunnel_remote = { host = data.aws_rds_cluster.cluster.endpoint port = local.is_mysql ? 3306 : 5432 diff --git a/cloud/aws/rds_serverless/tenant/input.tf b/cloud/aws/rds_serverless/tenant/input.tf index 21dd935..eb47633 100644 --- a/cloud/aws/rds_serverless/tenant/input.tf +++ b/cloud/aws/rds_serverless/tenant/input.tf @@ -32,29 +32,11 @@ locals { database = lower(var.database) password = try(random_password.password[0].result, var.password) } -variable "app_name" { - type = string - description = "The application name" -} - variable "tags" { type = map(string) description = "Tags to apply to resources" default = {} } -variable "aws_profile" { - type = string - description = "AWS profile to use for generating RDS auth token" - default = null -} -variable "is_active" { - type = bool - default = true -} -variable "super_user_iam_role_name" { - type = string - default = null -} variable "engine" { type = string description = "The engine type of the RDS cluster" @@ -63,6 +45,10 @@ variable "engine" { condition = var.engine == "aurora-postgres" || var.engine == "aurora-mysql" } } +locals { + is_mysql = var.engine == "aurora-mysql" + is_postgres = var.engine == "aurora-postgres" +} variable "mysql_binary" { type = string description = "The path to the mysql binary" diff --git a/cloud/aws/rds_serverless/tenants.tf b/cloud/aws/rds_serverless/tenants.tf index b2a632b..b4bea22 100644 --- a/cloud/aws/rds_serverless/tenants.tf +++ b/cloud/aws/rds_serverless/tenants.tf @@ -4,9 +4,7 @@ module "tenants" { source = "./tenant" username = each.value.username database = each.value.database - app_name = local.app_name vpc_id = data.aws_vpc.current.id - aws_profile = var.aws_profile cluster_id = aws_rds_cluster.cluster.id engine = aws_rds_cluster.cluster.engine admin_username = local.admin_username