diff --git a/.gitignore b/.gitignore index 2c2c729..e3b6ea9 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ terraform.rc .terragrunt-cache/ terragrunt.hcl.backup - +# Exception: commit lock files for dependencies to ensure consistent provider versions !live/stage/s3/.terraform.lock.hcl !live/stage/database/.terraform.lock.hcl !live/stage/namespace/.terraform.lock.hcl diff --git a/infrastructure.yaml b/infrastructure.yaml index a8ea989..c098806 100644 --- a/infrastructure.yaml +++ b/infrastructure.yaml @@ -7,6 +7,11 @@ environments: project: pulse annotations: managed-by: terraform + - name: block-analyzer + labels: + project: block-analyzer + annotations: + managed-by: terraform secrets: - name: dockerhub @@ -28,7 +33,24 @@ environments: db: pulse_db user: pulse lifecycle: - ignore_changes: false + ignore_changes: true + + - name: analyzer-postgresql-secret + namespace: block-analyzer + type: database + dependencies: + cluster: "c9qa2coo5ukgcg93fldm" + db: analyzer_db + user: analyzer + custom_keys: + sslmode: "verify-full" + random_keys: + full-host: + length: 32 + special: false + lifecycle: + ignore_changes: true + - name: session-secret namespace: pulse @@ -40,20 +62,20 @@ environments: lifecycle: ignore_changes: true - # Пример секрета для другой базы данных (test_db/test) - - name: test-db-secret - namespace: pulse - type: database - dependencies: - cluster: "c9qa2coo5ukgcg93fldm" - db: test_db - user: test - random_keys: - session_key: - length: 32 - special: false - lifecycle: - ignore_changes: false + # # Пример секрета для другой базы данных (test_db/test) + # - name: test-db-secret + # namespace: pulse + # type: database + # dependencies: + # cluster: "c9qa2coo5ukgcg93fldm" + # db: test_db + # user: test + # random_keys: + # session_key: + # length: 32 + # special: false + # lifecycle: + # ignore_changes: false buckets: - name: pulse-stage @@ -77,3 +99,61 @@ environments: password_length: 32 password_special: false conn_limit: 10 + - cluster_id: "c9qa2coo5ukgcg93fldm" + database: + name: analyzer_db + extensions: + - pg_stat_statements + user: + name: analyzer + password_length: 32 + password_special: false + conn_limit: 10 + permissions: + - pulse_db + - attachments_db + - automation_db + - bi_db + - bim_db + - bimv2_db + - camera_db + - camunda_db + - checklists_db + - comparator_db + - comparisons_db + - contracts_db + - document-understanding + - documentations_db + - drawings_db + - eav_db + - flow + - ingrad-notifications + - inspections_db + - issues_db + - keycloak + - mailer_db + - mcc + - metrics + - mvp-agents + - notes_db + - orchestrator + - pm-backend + - processing_db + - remarks_db + - resources_db + - rfi_db + - sarex-management + - sarex-compute + - sarex_db + - srx-data-engine_db + - stage-sarex + - subscriptions_db + - superset_db + - system-log_db + - test_db + - transmittals_db + - workspaces_db + - zitadel + - zitadel-new + + diff --git a/live/stage/database/.terraform.lock.hcl b/live/stage/database/.terraform.lock.hcl deleted file mode 100644 index ec1babe..0000000 --- a/live/stage/database/.terraform.lock.hcl +++ /dev/null @@ -1,26 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/kubernetes" { - version = "2.38.0" - constraints = "~> 2.23" - hashes = [ - "h1:soK8Lt0SZ6dB+HsypFRDzuX/npqlMU6M0fvyaR1yW0k=", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.8.0" - constraints = "~> 3.1" - hashes = [ - "h1:BYpqK2+ZHqNF9sauVugKJSeFWMCx11I/z/1lMplwUC0=", - ] -} - -provider "registry.terraform.io/yandex-cloud/yandex" { - version = "0.181.0" - constraints = "~> 0.100" - hashes = [ - "h1:n5o9pvUkrGmunWVvZU4xGEUtfRXAG3KCvR9YrzsXc08=", - ] -} diff --git a/live/stage/database/terragrunt.hcl b/live/stage/database/terragrunt.hcl index 0ba0a4d..beb31de 100644 --- a/live/stage/database/terragrunt.hcl +++ b/live/stage/database/terragrunt.hcl @@ -1,4 +1,3 @@ - include "root" { path = find_in_parent_folders() } @@ -10,11 +9,10 @@ include "env" { } locals { - repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..") + repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..") infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml")) - env_name = basename(dirname(get_terragrunt_dir())) + env_name = basename(dirname(get_terragrunt_dir())) env_config = local.infra_config.environments[local.env_name] - db_config = local.env_config.databases[0] # Первая БД из списка } terraform { @@ -22,16 +20,11 @@ terraform { } inputs = { - cluster_id = local.db_config.cluster_id - database_name = local.db_config.database.name - user_name = local.db_config.user.name - password_length = try(local.db_config.user.password_length, 32) - password_special = try(local.db_config.user.password_special, false) - conn_limit = try(local.db_config.user.conn_limit, 10) - - yc_token = get_env("YC_TOKEN", "") - yc_cloud_id = get_env("YC_CLOUD_ID", "") - yc_folder_id = get_env("YC_STAGE_FOLDER_ID", get_env("YC_FOLDER_ID", "")) + databases = local.env_config.databases + + yc_token = get_env("YC_TOKEN", "") + yc_cloud_id = get_env("YC_CLOUD_ID", "") + yc_folder_id = get_env("YC_STAGE_FOLDER_ID", get_env("YC_FOLDER_ID", "")) kubeconfig_path = get_env("KUBECONFIG", "") - kube_context = get_env("KUBE_CONTEXT", "") + kube_context = get_env("KUBE_CONTEXT", "") } diff --git a/live/stage/namespace/.terraform.lock.hcl b/live/stage/namespace/.terraform.lock.hcl deleted file mode 100644 index ec1babe..0000000 --- a/live/stage/namespace/.terraform.lock.hcl +++ /dev/null @@ -1,26 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/kubernetes" { - version = "2.38.0" - constraints = "~> 2.23" - hashes = [ - "h1:soK8Lt0SZ6dB+HsypFRDzuX/npqlMU6M0fvyaR1yW0k=", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.8.0" - constraints = "~> 3.1" - hashes = [ - "h1:BYpqK2+ZHqNF9sauVugKJSeFWMCx11I/z/1lMplwUC0=", - ] -} - -provider "registry.terraform.io/yandex-cloud/yandex" { - version = "0.181.0" - constraints = "~> 0.100" - hashes = [ - "h1:n5o9pvUkrGmunWVvZU4xGEUtfRXAG3KCvR9YrzsXc08=", - ] -} diff --git a/live/stage/namespace/terragrunt.hcl b/live/stage/namespace/terragrunt.hcl index df1509c..ce8ed56 100644 --- a/live/stage/namespace/terragrunt.hcl +++ b/live/stage/namespace/terragrunt.hcl @@ -1,4 +1,3 @@ - include "root" { path = find_in_parent_folders() } @@ -10,11 +9,10 @@ include "env" { } locals { - repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..") + repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..") infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml")) - env_name = basename(dirname(get_terragrunt_dir())) + env_name = basename(dirname(get_terragrunt_dir())) env_config = local.infra_config.environments[local.env_name] - namespace = local.env_config.namespaces[0] # Первый namespace из списка } terraform { @@ -22,13 +20,11 @@ terraform { } inputs = { - namespace_name = local.namespace.name - labels = local.namespace.labels - annotations = local.namespace.annotations - - yc_token = get_env("YC_TOKEN", "") - yc_cloud_id = get_env("YC_CLOUD_ID", "") - yc_folder_id = get_env("YC_STAGE_FOLDER_ID", get_env("YC_FOLDER_ID", "")) + namespaces = local.env_config.namespaces + + yc_token = get_env("YC_TOKEN", "") + yc_cloud_id = get_env("YC_CLOUD_ID", "") + yc_folder_id = get_env("YC_STAGE_FOLDER_ID", get_env("YC_FOLDER_ID", "")) kubeconfig_path = get_env("KUBECONFIG", "") - kube_context = get_env("KUBE_CONTEXT", "") + kube_context = get_env("KUBE_CONTEXT", "") } diff --git a/live/stage/s3/.terraform.lock.hcl b/live/stage/s3/.terraform.lock.hcl deleted file mode 100644 index ec1babe..0000000 --- a/live/stage/s3/.terraform.lock.hcl +++ /dev/null @@ -1,26 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/kubernetes" { - version = "2.38.0" - constraints = "~> 2.23" - hashes = [ - "h1:soK8Lt0SZ6dB+HsypFRDzuX/npqlMU6M0fvyaR1yW0k=", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.8.0" - constraints = "~> 3.1" - hashes = [ - "h1:BYpqK2+ZHqNF9sauVugKJSeFWMCx11I/z/1lMplwUC0=", - ] -} - -provider "registry.terraform.io/yandex-cloud/yandex" { - version = "0.181.0" - constraints = "~> 0.100" - hashes = [ - "h1:n5o9pvUkrGmunWVvZU4xGEUtfRXAG3KCvR9YrzsXc08=", - ] -} diff --git a/live/stage/secrets/.terraform.lock.hcl b/live/stage/secrets/.terraform.lock.hcl index ec1babe..63698be 100644 --- a/live/stage/secrets/.terraform.lock.hcl +++ b/live/stage/secrets/.terraform.lock.hcl @@ -1,26 +1,26 @@ -# This file is maintained automatically by "terraform init". +# This file is maintained automatically by "tofu init". # Manual edits may be lost in future updates. -provider "registry.terraform.io/hashicorp/kubernetes" { +provider "registry.opentofu.org/hashicorp/kubernetes" { version = "2.38.0" constraints = "~> 2.23" hashes = [ - "h1:soK8Lt0SZ6dB+HsypFRDzuX/npqlMU6M0fvyaR1yW0k=", + "h1:ems+O2dA7atxMWpbtqIrsH7Oa+u+ERWSfpMaFnZPbh0=", ] } -provider "registry.terraform.io/hashicorp/random" { - version = "3.8.0" +provider "registry.opentofu.org/hashicorp/random" { + version = "3.8.1" constraints = "~> 3.1" hashes = [ - "h1:BYpqK2+ZHqNF9sauVugKJSeFWMCx11I/z/1lMplwUC0=", + "h1:LsYuJLZcYl1RiH7Hd3w90Ra5+k5cNqfdRUQXItkTI8Y=", ] } -provider "registry.terraform.io/yandex-cloud/yandex" { - version = "0.181.0" +provider "registry.opentofu.org/yandex-cloud/yandex" { + version = "0.127.0" constraints = "~> 0.100" hashes = [ - "h1:n5o9pvUkrGmunWVvZU4xGEUtfRXAG3KCvR9YrzsXc08=", + "h1:tms24VWADoryHdkGdH5A76fWG2k+9CrE9Je9yZMXUoI=", ] } diff --git a/live/stage/secrets/terragrunt.hcl b/live/stage/secrets/terragrunt.hcl index 9760564..d983099 100644 --- a/live/stage/secrets/terragrunt.hcl +++ b/live/stage/secrets/terragrunt.hcl @@ -11,7 +11,11 @@ include "env" { dependency "namespace" { config_path = "../namespace" mock_outputs = { - name = "pulse" + namespaces = { + "pulse" = { name = "pulse", id = "mock-id-1" } + "block-analyzer" = { name = "block-analyzer", id = "mock-id-2" } + } + names = ["pulse", "block-analyzer"] } mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"] } @@ -29,10 +33,20 @@ dependency "s3" { dependency "database" { config_path = "../database" mock_outputs = { - host = "mock-host.example.com" - database_name = "pulse_db" - user_name = "pulse" - password = "mock-password" + database_outputs_map = { + "c9qa2coo5ukgcg93fldm:pulse_db:pulse" = { + host = "mock-host.example.com" + database_name = "pulse_db" + user_name = "pulse" + password = "mock-password" + } + "c9qa2coo5ukgcg93fldm:analyzer_db:analyzer" = { + host = "mock-host.example.com" + database_name = "analyzer_db" + user_name = "analyzer" + password = "mock-password" + } + } } mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"] } @@ -100,11 +114,10 @@ LpuQKbSbIERsmR+QqQ== -----END CERTIFICATE----- EOT - repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..") + repo_root = try(get_repo_root(), "${get_terragrunt_dir()}/../../..") infra_config = yamldecode(file("${local.repo_root}/infrastructure.yaml")) - env_name = basename(dirname(get_terragrunt_dir())) + env_name = basename(dirname(get_terragrunt_dir())) env_config = local.infra_config.environments[local.env_name] - secrets = local.env_config.secrets } terraform { @@ -113,49 +126,42 @@ terraform { inputs = { secrets = [ - for secret in local.secrets : { - name = secret.name - namespace = dependency.namespace.outputs.name - secret_type = secret.type - registry_url = try(secret.registry_url, "") - dependencies = try(secret.dependencies, {}) - custom_keys = try(secret.custom_keys, {}) - random_keys = try(secret.random_keys, {}) - labels = try(secret.labels, {}) - annotations = try(secret.annotations, {}) + for secret in local.env_config.secrets : { + name = secret.name + namespace = secret.namespace + secret_type = secret.type + registry_url = try(secret.registry_url, "") + dependencies = try(secret.dependencies, {}) + custom_keys = try(secret.custom_keys, {}) + random_keys = try(secret.random_keys, {}) + labels = try(secret.labels, {}) + annotations = try(secret.annotations, {}) ignore_changes = try(secret.lifecycle.ignore_changes, false) } ] - + s3_outputs = { bucket_name = dependency.s3.outputs.bucket_name access_key = dependency.s3.outputs.access_key secret_key = dependency.s3.outputs.secret_key } - - database_outputs_map = { - "${local.env_config.databases[0].cluster_id}:${local.env_config.databases[0].database.name}:${local.env_config.databases[0].user.name}" = { - host = dependency.database.outputs.host - database_name = dependency.database.outputs.database_name - user_name = dependency.database.outputs.user_name - password = dependency.database.outputs.password - } - } - + + database_outputs_map = dependency.database.outputs.database_outputs_map + constants = { s3_endpoint = "https://storage.yandexcloud.net" postgres_port = "6432" postgres_ca = local.yc_postgresql_ca_cert } - + env_vars = { DOCKER_REGISTRY_USERNAME = get_env("DOCKER_REGISTRY_USERNAME", "") DOCKER_REGISTRY_PASSWORD = get_env("DOCKER_REGISTRY_PASSWORD", "") } - - yc_token = get_env("YC_TOKEN", "") - yc_cloud_id = get_env("YC_CLOUD_ID", "") - yc_folder_id = get_env("YC_STAGE_FOLDER_ID", get_env("YC_FOLDER_ID", "")) + + yc_token = get_env("YC_TOKEN", "") + yc_cloud_id = get_env("YC_CLOUD_ID", "") + yc_folder_id = get_env("YC_STAGE_FOLDER_ID", get_env("YC_FOLDER_ID", "")) kubeconfig_path = get_env("KUBECONFIG", "") - kube_context = get_env("KUBE_CONTEXT", "") + kube_context = get_env("KUBE_CONTEXT", "") } diff --git a/live/terragrunt.hcl b/live/terragrunt.hcl index 462bd07..e03c29c 100644 --- a/live/terragrunt.hcl +++ b/live/terragrunt.hcl @@ -14,7 +14,7 @@ remote_state { skip_region_validation = true skip_credentials_validation = true skip_metadata_api_check = true - force_path_style = true + use_path_style = true skip_bucket_root_access = true } } diff --git a/modules/k8s-namespace/main.tf b/modules/k8s-namespace/main.tf index a49cf99..5ec9aa8 100644 --- a/modules/k8s-namespace/main.tf +++ b/modules/k8s-namespace/main.tf @@ -1,13 +1,15 @@ -# Создание namespace в Kubernetes -resource "kubernetes_namespace" "pulse" { +# Создание namespace'ов в Kubernetes +resource "kubernetes_namespace" "this" { + for_each = { for ns in var.namespaces : ns.name => ns } + metadata { - name = var.namespace_name + name = each.value.name labels = merge( { - name = var.namespace_name + name = each.value.name }, - var.labels + try(each.value.labels, {}) ) - annotations = var.annotations + annotations = try(each.value.annotations, {}) } } diff --git a/modules/k8s-namespace/outputs.tf b/modules/k8s-namespace/outputs.tf index 14fb552..9871f5f 100644 --- a/modules/k8s-namespace/outputs.tf +++ b/modules/k8s-namespace/outputs.tf @@ -1,9 +1,14 @@ -output "name" { - description = "Name of the created namespace" - value = kubernetes_namespace.pulse.metadata[0].name +output "namespaces" { + description = "Map of created namespaces (name => namespace data)" + value = { + for name, ns in kubernetes_namespace.this : name => { + name = ns.metadata[0].name + id = ns.id + } + } } -output "id" { - description = "ID of the created namespace" - value = kubernetes_namespace.pulse.id +output "names" { + description = "List of namespace names" + value = [for name, ns in kubernetes_namespace.this : ns.metadata[0].name] } diff --git a/modules/k8s-namespace/variables.tf b/modules/k8s-namespace/variables.tf index 1341cef..a3c5912 100644 --- a/modules/k8s-namespace/variables.tf +++ b/modules/k8s-namespace/variables.tf @@ -1,16 +1,8 @@ -variable "namespace_name" { - description = "Name of the Kubernetes namespace" - type = string -} - -variable "labels" { - description = "Labels for the namespace" - type = map(string) - default = {} -} - -variable "annotations" { - description = "Annotations for the namespace" - type = map(string) - default = {} +variable "namespaces" { + description = "List of Kubernetes namespaces to create" + type = list(object({ + name = string + labels = optional(map(string), {}) + annotations = optional(map(string), {}) + })) } diff --git a/modules/k8s-secret/main.tf b/modules/k8s-secret/main.tf index d5ea9e1..241d728 100644 --- a/modules/k8s-secret/main.tf +++ b/modules/k8s-secret/main.tf @@ -1,6 +1,14 @@ locals { + # Маппинг наших типов на Kubernetes типы + k8s_secret_type_map = { + "dockerconfigjson" = "kubernetes.io/dockerconfigjson" + "database" = "Opaque" + "s3" = "Opaque" + "opaque" = "Opaque" + } + secrets_map = { for idx, secret in var.secrets : secret.name => secret } @@ -40,16 +48,23 @@ locals { secret_key = var.s3_outputs.secret_key bucket = var.s3_outputs.bucket_name endpoint = try(var.constants.s3_endpoint, "https://storage.yandexcloud.net") - } : secret.secret_type == "database" && local.database_outputs_by_secret[name] != null ? merge({ - host = local.database_outputs_by_secret[name].host - port = try(var.constants.postgres_port, "6432") - database = local.database_outputs_by_secret[name].database_name - user = local.database_outputs_by_secret[name].user_name - password = local.database_outputs_by_secret[name].password - "ca.crt" = try(var.constants.postgres_ca, "") - }, { - for key, config in try(secret.random_keys, {}) : key => random_password.secrets["${name}:${key}"].result - }) : merge( + } : secret.secret_type == "database" && local.database_outputs_by_secret[name] != null ? merge( + # Базовые поля из database outputs + { + host = local.database_outputs_by_secret[name].host + port = try(var.constants.postgres_port, "6432") + database = local.database_outputs_by_secret[name].database_name + username = local.database_outputs_by_secret[name].user_name + password = local.database_outputs_by_secret[name].password + "ca.crt" = try(var.constants.postgres_ca, "") + }, + # Кастомные статические поля + try(secret.custom_keys, {}), + # Рандомные поля + { + for key, config in try(secret.random_keys, {}) : key => random_password.secrets["${name}:${key}"].result + } + ) : merge( try(secret.custom_keys, {}), { for key, config in try(secret.random_keys, {}) : key => random_password.secrets["${name}:${key}"].result @@ -59,13 +74,14 @@ locals { secrets_with_data = { for name, secret in local.secrets_map : name => { - name = secret.name - namespace = secret.namespace - secret_type = secret.secret_type - labels = try(secret.labels, {}) - annotations = try(secret.annotations, {}) + name = secret.name + namespace = secret.namespace + secret_type = secret.secret_type + k8s_type = try(local.k8s_secret_type_map[secret.secret_type], "Opaque") + labels = try(secret.labels, {}) + annotations = try(secret.annotations, {}) ignore_changes = try(secret.ignore_changes, false) - data = try(local.secrets_data[name], {}) + data = try(local.secrets_data[name], {}) } } @@ -99,14 +115,15 @@ resource "kubernetes_secret" "with_ignore" { annotations = try(each.value.annotations, {}) } - type = each.value.secret_type + type = each.value.k8s_type data = each.value.data lifecycle { - ignore_changes = [data] + # type игнорируем чтобы не пересоздавать из-за opaque->Opaque + ignore_changes = [data, type] } - + depends_on = [random_password.secrets] } @@ -120,9 +137,14 @@ resource "kubernetes_secret" "without_ignore" { annotations = try(each.value.annotations, {}) } - type = each.value.secret_type + type = each.value.k8s_type data = each.value.data - + + lifecycle { + # type игнорируем чтобы не пересоздавать из-за opaque->Opaque + ignore_changes = [type] + } + depends_on = [random_password.secrets] } diff --git a/modules/yc-database/main.tf b/modules/yc-database/main.tf index 41b4cd2..6154c31 100644 --- a/modules/yc-database/main.tf +++ b/modules/yc-database/main.tf @@ -1,41 +1,53 @@ +locals { + databases_map = { for db in var.databases : "${db.cluster_id}:${db.database.name}:${db.user.name}" => db } +} resource "random_password" "user_password" { - length = var.password_length - special = var.password_special + 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 } data "yandex_mdb_postgresql_cluster" "existing" { - cluster_id = var.cluster_id + for_each = toset([for db in var.databases : db.cluster_id]) + cluster_id = each.value } resource "yandex_mdb_postgresql_user" "this" { - cluster_id = var.cluster_id - name = var.user_name - password = random_password.user_password.result - conn_limit = var.conn_limit + for_each = local.databases_map + cluster_id = each.value.cluster_id + name = each.value.user.name + password = random_password.user_password[each.key].result + conn_limit = try(each.value.user.conn_limit, 10) + + # permissions только для ДРУГИХ существующих БД + # на свою БД user получает права автоматически как owner dynamic "permission" { - for_each = length(var.permissions) > 0 ? var.permissions : [] + for_each = distinct(compact(try(each.value.user.permissions, []))) content { - database_name = permission.value.database_name + database_name = permission.value } } } resource "yandex_mdb_postgresql_database" "this" { - cluster_id = var.cluster_id - name = var.database_name - owner = yandex_mdb_postgresql_user.this.name - lc_collate = var.lc_collate - lc_type = var.lc_type + for_each = local.databases_map + + cluster_id = each.value.cluster_id + name = each.value.database.name + owner = yandex_mdb_postgresql_user.this[each.key].name + lc_collate = try(each.value.database.lc_collate, "en_US.UTF-8") + lc_type = try(each.value.database.lc_type, "en_US.UTF-8") depends_on = [yandex_mdb_postgresql_user.this] dynamic "extension" { - for_each = var.extensions + for_each = try(each.value.database.extensions, []) content { name = extension.value } diff --git a/modules/yc-database/outputs.tf b/modules/yc-database/outputs.tf index 799a2ad..3e8e70e 100644 --- a/modules/yc-database/outputs.tf +++ b/modules/yc-database/outputs.tf @@ -1,35 +1,27 @@ -output "cluster_id" { - description = "ID кластера PostgreSQL" - value = var.cluster_id +output "databases" { + description = "Map of created databases (cluster_id:db_name:user_name => data)" + value = { + for key, db in local.databases_map : key => { + cluster_id = db.cluster_id + host = try(data.yandex_mdb_postgresql_cluster.existing[db.cluster_id].host[0].fqdn, "") + port = 6432 + database_name = yandex_mdb_postgresql_database.this[key].name + user_name = yandex_mdb_postgresql_user.this[key].name + password = random_password.user_password[key].result + } + } + sensitive = true } -output "cluster_fqdn" { - description = "FQDN кластера PostgreSQL" - value = data.yandex_mdb_postgresql_cluster.existing.host[0].fqdn -} - -output "host" { - description = "Host адрес кластера" - value = data.yandex_mdb_postgresql_cluster.existing.host[0].fqdn -} - -output "port" { - description = "Порт кластера" - value = 6432 -} - -output "database_name" { - description = "Имя базы данных" - value = yandex_mdb_postgresql_database.this.name -} - -output "user_name" { - description = "Имя пользователя" - value = yandex_mdb_postgresql_user.this.name -} - -output "password" { - description = "Пароль пользователя" - value = random_password.user_password.result - sensitive = true +output "database_outputs_map" { + description = "Map for secrets module (cluster_id:db_name:user_name => credentials)" + value = { + for key, db in local.databases_map : key => { + host = try(data.yandex_mdb_postgresql_cluster.existing[db.cluster_id].host[0].fqdn, "") + database_name = yandex_mdb_postgresql_database.this[key].name + user_name = yandex_mdb_postgresql_user.this[key].name + password = random_password.user_password[key].result + } + } + sensitive = true } diff --git a/modules/yc-database/variables.tf b/modules/yc-database/variables.tf index 231be1d..16b2a8b 100644 --- a/modules/yc-database/variables.tf +++ b/modules/yc-database/variables.tf @@ -1,58 +1,19 @@ -variable "cluster_id" { - description = "ID существующего PostgreSQL кластера в Yandex Cloud" - type = string -} - -variable "database_name" { - description = "Имя базы данных" - type = string -} - -variable "user_name" { - description = "Имя пользователя" - type = string -} - -variable "password_length" { - description = "Длина пароля" - type = number - default = 32 -} - -variable "password_special" { - description = "Использовать специальные символы в пароле" - type = bool - default = false -} - -variable "lc_collate" { - description = "LC_COLLATE для базы данных" - type = string - default = "en_US.UTF-8" -} - -variable "lc_type" { - description = "LC_TYPE для базы данных" - type = string - default = "en_US.UTF-8" -} - -variable "extensions" { - description = "Список расширений PostgreSQL" - type = list(string) - default = [] -} - -variable "permissions" { - description = "Права доступа пользователя" +variable "databases" { + description = "List of databases to create" type = list(object({ - database_name = string + cluster_id = string + database = object({ + name = string + lc_collate = optional(string, "en_US.UTF-8") + lc_type = optional(string, "en_US.UTF-8") + extensions = optional(list(string), []) + }) + user = object({ + name = string + password_length = optional(number, 32) + password_special = optional(bool, false) + conn_limit = optional(number, 10) + permissions = optional(list(string), []) + }) })) - default = [] -} - -variable "conn_limit" { - description = "Лимит подключений для пользователя" - type = number - default = 10 } diff --git a/scripts/generate-pipeline.sh b/scripts/generate-pipeline.sh index 3e893cf..c41a758 100755 --- a/scripts/generate-pipeline.sh +++ b/scripts/generate-pipeline.sh @@ -99,6 +99,7 @@ validate-${job_prefix}: - export TF_PLUGIN_CACHE_DIR=/root/.terraform.d/plugin-cache script: - env | grep -E "(S3_|AWS_)" || echo "No S3/AWS vars found" + - rm -f .terraform.lock.hcl - terragrunt init -upgrade -reconfigure - terragrunt validate rules: