terraform-contour-mirror/modules/pg-incluster/main.tf

80 lines
2.4 KiB
HCL

# In-cluster PostgreSQL implementation of the `databases` entity contract.
# Same `databases` list + same output maps as modules/yc-database, so the shared
# k8s-secret module resolves credentials identically. `cluster_id` is a logical
# key only (all databases are created on the single server the root provider
# points at); host/port in outputs come from the database's own host or default_*.
locals {
databases_map = { for db in var.databases : "${db.cluster_id}:${db.database.name}:${db.user.name}" => db }
db_extensions = merge([
for key, db in local.databases_map : {
for ext in try(db.database.extensions, []) : "${key}:${ext}" => { key = key, ext = ext }
}
]...)
db_grants = merge([
for key, db in local.databases_map : {
for perm in distinct(compact(try(db.user.permissions, []))) : "${key}:${perm}" => { key = key, db = perm }
}
]...)
}
resource "random_password" "user_password" {
for_each = local.databases_map
length = try(each.value.user.password_length, 32)
special = try(each.value.user.password_special, false)
upper = true
lower = true
numeric = true
lifecycle {
ignore_changes = all
}
}
resource "postgresql_role" "this" {
for_each = local.databases_map
name = each.value.user.name
login = true
password = random_password.user_password[each.key].result
connection_limit = try(each.value.user.conn_limit, 10)
lifecycle {
ignore_changes = [password]
}
}
resource "postgresql_database" "this" {
for_each = local.databases_map
name = each.value.database.name
owner = postgresql_role.this[each.key].name
lc_collate = try(each.value.database.lc_collate, "en_US.UTF-8")
lc_ctype = try(each.value.database.lc_type, "en_US.UTF-8")
# template0 is required when the collation/ctype differ from the server default.
template = "template0"
depends_on = [postgresql_role.this]
}
resource "postgresql_extension" "this" {
for_each = local.db_extensions
name = each.value.ext
database = postgresql_database.this[each.value.key].name
}
# CONNECT grants to OTHER existing databases (declared in user.permissions);
# the owner already has full access to its own database.
resource "postgresql_grant" "connect" {
for_each = local.db_grants
role = postgresql_role.this[each.value.key].name
database = each.value.db
object_type = "database"
privileges = ["CONNECT"]
}