variable "kubernetes_input" { type = map(object({ name = optional(string) environment = optional(map(object({ name = optional(string) value = optional(string) value_from = optional(object({ secret_key_ref = object({ name = string key = optional(string, null) }) })) }))) replicas = optional(number, 1) namespace = optional(string) connected_namespace = optional(string, "") database = optional(map(string)) database_args = optional(list(string)) enabled = optional(bool, true) })) } variable "database_backup_info" { type = map(object({ image = optional(string) command = optional(string) })) description = "based on DB engine, give the docker image and the command used to backup" default = { postgres = { image = "alpine/psql" command = "pg_dump |gzip -9 > /backup/$(DB_DATABASE_NAME)-DB-$(date +%Y%m%d).sql.gz" } mysql = { image = "mysql" command = "mysqldump -h $DB_HOST -u $MYSQL_USER -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE |gzip -9 > /backup/$(DB_DATABASE_NAME)-DB-$(date +%Y%m%d).sql.gz" } sqlserver = { image = "mcr.microsoft.com/mssql-tools" command = "/opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USERNAME -P $DB_PASSWORD -Q \"BACKUP DATABASE $DB_DATABASE_NAME TO DISK = '/backup/$DB_DATABASE_NAME-$(date +%Y%m%d).bak' WITH COPY_ONLY, CHECKSUM,FORMAT, MEDIANAME = 'SQLServerBackups',NAME = 'Full Backup of SQLTestDB'\";exit" } } } variable "storage_path" { type = map(string) default = { main_storage = "/data/kubernetes", fast_access = "/ssd" } } resource "kubernetes_deployment_v1" "database-automatic" { for_each = { for key, value in var.kubernetes_input : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) } metadata { namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key) name = "${coalesce(each.value.name, each.key)}-db" labels = { app = each.key deployment_method = "Terraform" database = "true" } } spec { replicas = each.value.replicas selector { match_labels = { app = "${each.key}-db" } } template { metadata { labels = { app = "${each.key}-db" deployment_method = "Terraform" database = "true" } } spec { container { image = try(each.value.database.image, "docker.io/library/postgres:latest") name = "${coalesce(each.value.name, each.key)}-db" port { container_port = 5432 name = "database-port" } volume_mount { mount_path = try(each.value.database.mountPath, "/var/lib/postgresql/") name = "${each.key}-db-volume" } dynamic "volume_mount" { for_each = try(each.value.database.engine == "sqlserver", false) && !(try(each.value.database.shunt, false)) ? [1] : [] content { mount_path = "/backup" name = "${each.key}-db-backup" } } command = try([each.value.database.command], []) args = each.value.database_args != null ? each.value.database_args : [] dynamic "env_from" { for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : [] content { dynamic "secret_ref" { for_each = [1] content { name = env_from.value } } } } dynamic "env" { for_each = each.value.environment != null ? each.value.environment : {} content { name = env.key value = env.value.value != null ? env.value.value : null dynamic "value_from" { for_each = env.value.value_from != null ? env.value.value_from : {} content { dynamic "secret_key_ref" { for_each = [1] content { name = env.value.value_from.secret_key_ref.name key = env.value.value_from.secret_key_ref.key } } } } } } } volume { name = "${each.key}-db-volume" host_path { path = try(each.value.database.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), join("-", [each.key, "db"])])) } } dynamic "volume" { for_each = try(each.value.database.engine == "sqlserver", false) && !(try(each.value.database.shunt, false)) ? [1] : [] content { name = "${each.key}-db-backup" host_path { path = join("/", [var.storage_path.fast_access, "Backup", coalesce(each.value.namespace, each.value.connected_namespace, each.key), "${each.key}-db-backup"]) } } } } } } } resource "kubernetes_cron_job_v1" "database-backup" { for_each = { for key, value in var.kubernetes_input : key => value if value.database != null && value.enabled == true } metadata { name = "${coalesce(each.value.namespace, each.key)}-db-backup" namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key) labels = { app = each.key deployment_method = "Terraform" database = "true" } } spec { failed_jobs_history_limit = 5 schedule = "1 0 * * *" timezone = "Etc/UTC" successful_jobs_history_limit = 5 job_template { metadata {} spec { backoff_limit = 4 ttl_seconds_after_finished = 100 template { metadata {} spec { container { name = "${coalesce(each.value.namespace, each.key)}-db-backup" image = try(var.database_backup_info[each.value.database.engine].image, var.database_backup_info.postgres.image) command = ["/bin/sh", "-c"] args = [try(var.database_backup_info[each.value.database.engine].command, var.database_backup_info.postgres.command)] env_from { secret_ref { name = "${each.key}-db-terraform" } } volume_mount { mount_path = "/backup" name = "${each.key}-db-backup" } } volume { name = "${each.key}-db-backup" host_path { path = join("/", [var.storage_path.fast_access, "Backup", coalesce(each.value.namespace, each.value.connected_namespace, each.key), "${each.key}-db-backup"]) } } } } } } } }