LINUX.ORG.RU

Как выполнить несколько SQL-команд для PostgreSQL в Ansible?

 , ,


0

2

Имеется Astra Linux 1.3, PostgreSQL 9.1.6, Ansible 2.9.16

В инстансе базы данных неожиданно перестали создаваться таблицы.

Создание таблицы приводит к ошибке:

  - name: Create a new database impulse
    postgresql_db:
      name: impulse
      encoding: UTF-8
      lc_collate: ru_RU.UTF-8
      lc_ctype: ru_RU.UTF-8
      owner: impUser
...
FAILED! => 
{"changed": false, 
 "msg": "Database query failed: 
         new encoding (UTF8) is incompatible with the encoding 
         of the template database (SQL_ASCII)\n
         ПОДСКАЗКА:  Use the same encoding as in
         the template database, or use template0 as template.\n"}

Чтобы исправить эту ошибку, необходимо выполнить следующий SQL-скрипт (взят отсюда):
  - name: Исправление кодировки шаблона базы данных
    postgresql_query:
      query: |
        update pg_database set datallowconn = TRUE where datname = 'template0';
        update pg_database set datistemplate = FALSE where datname = 'template1';
        drop database template1;
        create database template1 with encoding = 'UTF-8' lc_collate = 'ru_RU.UTF8' lc_ctype = 'ru_RU.UTF8' template = template0;
        update pg_database set datistemplate = TRUE where datname = 'template1';
        update pg_database set datallowconn = FALSE where datname = 'template0';

Однако выполнение такого плейбука завершается ошибкой:
FAILED! => {"changed": false, 
"msg": "Cannot execute SQL 'drop database template1;\n
create database template1 with encoding = 'UTF-8' 
lc_collate = 'ru_RU.UTF8' lc_ctype = 'ru_RU.UTF8' 
template = template0;\n'

None: DROP DATABASE cannot run inside a transaction block\n"}

То есть, похоже, что Ansible сама заворачивает выполнение SQL-команд в транзакцию. Я нашел тему, что можно принудительно сначала завершить транзакцию, а потом ее открыть. То есть получится, что сначала выполняется пустая транзакция, потом SQL-команды вне транзакции, и потом опять пустая транзакция:
  - name: Исправление кодировки шаблона базы данных
    postgresql_query:
      query: |
        end; 
        update pg_database set datallowconn = TRUE where datname = 'template0';
        update pg_database set datistemplate = FALSE where datname = 'template1';
        drop database template1;
        create database template1 with encoding = 'UTF-8' lc_collate = 'ru_RU.UTF8' lc_ctype = 'ru_RU.UTF8' template = template0;
        update pg_database set datistemplate = TRUE where datname = 'template1';
        update pg_database set datallowconn = FALSE where datname = 'template0';
        begin;

Но тогда появляется другая ошибка:
FAILED! => {
"changed": false, 
"msg": "Cannot execute SQL 
'end;\n
update pg_database set datallowconn = TRUE where datname = 'template0';\n
update pg_database set datistemplate = FALSE where datname = 'template1';\n
drop database template1;\n
create database template1 with encoding = 'UTF-8' lc_collate = 'ru_RU.UTF8' lc_ctype = 'ru_RU.UTF8' template = template0;\n
update pg_database set datistemplate = TRUE where datname = 'template1';\n
update pg_database set datallowconn = FALSE where datname = 'template0';\n
begin;\n' 

None: DROP DATABASE cannot be executed from a function
or multi-command string\n"}

Далее я уже не могу придумать как обходить эти ограничения.

Вопрос: как в Ansible сделать простейшее действие: выполнить несколько SQL-команд?

★★★★★

В общем, обошел проблему по-тупому, через модуль shell:

---
- hosts: kmHosts
  become: true
  become_method: sudo
  become_user: postgres
  tasks:

  - name: Исправление кодировки шаблона базы данных
    shell: |
      cat > /tmp/sql.txt <<ENDOFFILE
      update pg_database set datallowconn = TRUE where datname = 'template0';
      update pg_database set datistemplate = FALSE where datname = 'template1';
      drop database template1;
      create database template1 with encoding = 'UTF-8' lc_collate = 'ru_RU.UTF-8' lc_ctype = 'ru_RU.UTF-8' template = template0;
      update pg_database set datistemplate = TRUE where datname = 'template1';
      update pg_database set datallowconn = FALSE where datname = 'template0';
      ENDOFFILE
      psql -f /tmp/sql.txt

Следует обратить внимание, что в названиях кодировки в начальном ТС есть проблеммка: вместо ru_RU.UTF8 надо писать ru_RU.UTF-8. Тогда все SQL-команды без ошибок начинают работать.

Xintrea ★★★★★ ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.