iac/aero/roles/sarex_stack/tasks/databases.yml
emelinda 6d6703ed2d BIM: расширение ltree и задача досоздания баз в живой СУБД
Продолжение разбора: после появления bimapidb оба пода упали на
  psycopg2.ProgrammingError: ltree type not found in the database
а миграция api — на
  type "ltree" does not exist
  LINE 2: ALTER TABLE bimelement ADD hierarchy ltree null;
models/database.py при инициализации зовёт register_ltree(conn), без
расширения приложение не стартует. Роль bim не суперпользователь и
CREATE EXTENSION сама не сделает — расширение обязан завести бутстрап,
как у sarex_db и workflow_db. Добавлено в contour.databases.

--- Почему понадобилась отдельная задача ansible ---

Базы и расширения описаны декларативно, но заводит их скрипт бутстрапа
ТОЛЬКО при старте пода postgresql. На живом кластере правка списка
доезжает до Kubernetes и не делает ничего: спецификация пода не меняется,
пересоздания нет. Flux при этом полностью зелёный, а приложение падает с
"database does not exist" — связь между причиной и симптомом неочевидна.

Альтернатива — перезапуск postgresql-0, но это обрыв коннектов django,
processing и workspaces ради одной базы.

Добавлены tasks/databases.yml, список sarex_databases в defaults и задача
`uv run poe dbsync`. Делает ровно то же, что бутстрап, но без простоя, и
идемпотентно: существующие базы пропускаются, расширения создаются через
IF NOT EXISTS. Расширения обрабатываются отдельным шагом и всегда, а не
только для новых баз, — расширение может появиться в списке позже самой
базы, ровно так и вышло с ltree.

Проверено на живом контуре: bim-api 2/2 (uWSGI поднял воркеров),
bim-worker 2/2 (celery подключился к брокеру, 8 задач зарегистрировано).
2026-08-09 21:55:27 +03:00

83 lines
4.3 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
# Досоздание баз в уже работающей СУБД.
#
# ЗАЧЕМ ЭТО ОТДЕЛЬНАЯ ЗАДАЧА. Базы описаны декларативно — contour.databases в
# infrastructure/postgresql/aero. Но заводит их скрипт бутстрапа, который
# выполняется ТОЛЬКО при старте пода postgresql. На живом кластере правка
# списка доезжает до Kubernetes (HelmRelease обновляется, Flux рапортует
# успех) и не делает ничего: под не пересоздаётся, потому что его
# спецификация не изменилась.
#
# Выглядит это так: приложение падает с
# psycopg2.OperationalError: FATAL: database "bimapidb" does not exist
# при полностью зелёном Flux. Так и случилось с bim.
#
# Альтернатива — перезапуск postgresql-0, но это обрыв коннектов у django,
# processing и workspaces ради одной новой базы. Здесь мы делаем ровно то же,
# что сделал бы бутстрап, но без простоя.
#
# ИДЕМПОТЕНТНО: существующие базы пропускаются, повторный прогон ничего не
# меняет. Ничего не удаляет и не пересоздаёт — только добавляет недостающее.
#
# Пароли ролям здесь НЕ задаются: роли и их пароли остаются за бутстрапом и
# Vault (secrets/postgresql/users). Если роли-владельца ещё нет, создание
# базы упадёт явно — это правильнее, чем завести её от postgres.
#
# Запуск: uv run poe dbsync
- name: Получить список существующих баз
ansible.builtin.shell:
cmd: >-
{{ compose_cmd }} exec -T k3s-server
kubectl -n postgresql exec postgresql-0 -c postgresql --
sh -ec 'PGPASSWORD=$POSTGRES_POSTGRES_PASSWORD psql -U postgres -tAc
"select datname from pg_database"'
chdir: "{{ deploy_dir }}"
register: existing_databases
changed_when: false
tags: [dbsync]
- name: Создать недостающие базы
ansible.builtin.shell:
cmd: >-
{{ compose_cmd }} exec -T k3s-server
kubectl -n postgresql exec postgresql-0 -c postgresql --
sh -ec 'PGPASSWORD=$POSTGRES_POSTGRES_PASSWORD psql -U postgres -c
"CREATE DATABASE \"{{ item.name }}\" OWNER \"{{ item.owner }}\""'
chdir: "{{ deploy_dir }}"
loop: "{{ sarex_databases }}"
loop_control:
label: "{{ item.name }} (владелец {{ item.owner }})"
when: item.name not in existing_databases.stdout_lines
changed_when: true
tags: [dbsync]
# Расширения создаются ОТДЕЛЬНЫМ шагом и всегда, а не только для новых баз:
# расширение могло появиться в списке позже самой базы — ровно так и вышло с
# ltree у bimapidb. CREATE EXTENSION IF NOT EXISTS идемпотентен.
#
# Выполняется от postgres, а не от владельца базы: роли приложений не
# суперпользователи и создать расширение не могут.
- name: Создать расширения в базах
ansible.builtin.shell:
cmd: >-
{{ compose_cmd }} exec -T k3s-server
kubectl -n postgresql exec postgresql-0 -c postgresql --
sh -ec 'PGPASSWORD=$POSTGRES_POSTGRES_PASSWORD psql -U postgres
-d "{{ item.0.name }}" -c
"CREATE EXTENSION IF NOT EXISTS \"{{ item.1 }}\""'
chdir: "{{ deploy_dir }}"
loop: "{{ sarex_databases | subelements('extensions', skip_missing=True) }}"
loop_control:
label: "{{ item.0.name }}: {{ item.1 }}"
changed_when: true
tags: [dbsync]
- name: Итог
ansible.builtin.debug:
msg: >-
Базы: {{ sarex_databases | map(attribute='name') | join(', ') }}.
Уже существовали: {{ sarex_databases | map(attribute='name')
| select('in', existing_databases.stdout_lines) | join(', ') | default('нет', true) }}
tags: [dbsync]