Запустите скрипт PostgreSQL с помощью Ansible

Я ищу способ запустить скрипт Postgres с помощью Ansible. Хотя я нашел достаточно хороший пример здесь мне нужно:

  • запустите скрипт от имени пользователя postgres
  • мне не обязательно хранить копию скрипта на сервере, поэтому, если мне нужно иметь копию, это будет только для временного использования.

может ли кто-нибудь сказать мне, возможно ли это, и если да, то пример его запуска. Вот что я пробовал до сих пор с помощью Ansible и это просто висели в этих точках:

 - name: Testing DB to make sure it is available
   command: psql -U bob image
   register: b
 - debug: b

 - name: Verifying Tables exist in Image
   shell: d image
   register: c
 - debug: c

 - name: Exiting Image DB
   shell: q
   register: d
 - debug: d

 - name: Going to Agent DB
   command: psql -U bob agent
   register: e
 - debug: e

это всегда зависает в первой части при входе в БД изображений.

3 ответов


почему это не работает

это:

 - name: Testing DB to make sure it is available
   command: psql -U bob image
   register: b
 - debug: b

 - name: Verifying Tables exist in Image
   shell: \d image
   register: c
 - debug: c

не делает то, что вы думаете, что он делает.

первая команда работает psql -U bob image. Это начинает psql сессии. psql ожидает ввода от stdin. Ansible никогда не будет отправлять их, он просто ждет команды, которую вы указали для выхода, поэтому он может проверить код выхода.

Итак, Анзибль ждет psql и psql ждет Ansible для отправки некоторого ввода.

каждой задачи в Анзибль является независимой. The shell или command модули не изменяют оболочку, в которой выполняются последующие команды. Вы просто не можете сделать это так, как вы ожидаете.

даже если psql вышел после первой задачи (или пошел в фоновом режиме), вы просто получите ошибку от второй задачи, как:

bash: d: command not found

таким образом, то, как вы пытаетесь это сделать, просто не сработает.

как это делается

вам нужно запускать каждую задачу как отдельную psql команда, с командной строкой:

 - name: Testing DB to make sure it is available
   command: psql -U bob image -c 'SELECT 1;'

 - name: Verifying Tables exist in Image
   command: psql -U bob image -c '\d image'

... или со стандартным вводом, за исключением того, что Ansible, похоже, не поддерживает предоставление переменной как stdin команде.

... или с (возможно, шаблонным) SQL-скриптом:

- name: Template sql script
  template:  src="my.sql.j2" dest="{{sometemplocation}}/my.sql"

- name: Execute sql script
  shell: "psql {{sometemplocation}}/my.sql"

- name: Delete sql script
  file: path="{{sometemplocation}}/my.sql" state=absent

в качестве альтернативы вы можете использовать встроенную поддержку Ansible для запроса PostgreSQL, но в этом случае вы не можете использовать psql команды обратной косой черты клиента, такие как \d, вам придется использовать только SQL. Запрос information_schema для данные по таблицы, etc.

вот как выглядит часть моего кода

вот пример из модуля автоматизации, который я написал, который много делает с PostgreSQL.

действительно, я должен просто смириться и написать psql Ansible задача, которая выполняет команды через psql, а не shell, что ужасно и неуклюже. Но пока это работает. Я использую строки подключения, назначенные из переменных или созданные с помощью set_fact уменьшить беспорядок немного и сделать соединения более гибкие.

- name: Wait for the target node to be ready to be joined
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_join_target_dsn}}' -qAtw 'SELECT bdr.bdr_node_join_wait_for_ready();'"

- name: Template pre-BDR-join SQL script
  template:  src="{{bdr_pre_join_sql_template}}" dest="{{postgres_install_dir}}/bdr_pre_join_{{inventory_hostname}}.sql"

- name: Execute pre-BDR-join SQL script
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_node_dsn}}' -qAtw -f {{postgres_install_dir}}/bdr_pre_join_{{inventory_hostname}}.sql"

- name: Delete pre-BDR-join SQL script
  file: path="{{postgres_install_dir}}/bdr_pre_join_{{inventory_hostname}}.sql" state=absent

- name: bdr_group_join
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_node_dsn}}' -qAtw -c \"SELECT bdr.bdr_group_join(local_node_name := '{{inventory_hostname}}', node_external_dsn := '{{bdr_node_dsn}}', join_using_dsn := '{{bdr_join_target_dsn}}');\""

- name: Template post-BDR-join SQL script
  template:  src="{{bdr_post_join_sql_template}}" dest="{{postgres_install_dir}}/bdr_post_join_{{inventory_hostname}}.sql"

- name: Execute post-BDR-join SQL script
  shell: "{{postgres_install_dir}}/bin/psql '{{bdr_node_dsn}}' -qAtw -f {{postgres_install_dir}}/bdr_post_join_{{inventory_hostname}}.sql"

- name: Delete post-BDR-join SQL script
  file: path="{{postgres_install_dir}}/bdr_post_join_{{inventory_hostname}}.sql" state=absent

ответ, который дает Крейг, хорош, но не решает проблему запуска команд в качестве конкретного пользователя. Это можно сделать с помощью моих дополнений к его коду:

- name: Testing DB to make sure it is available
  become: true
  become_user: postgres
  command: psql -U bob image -c 'SELECT 1;'

- name: Verifying Tables exist in Image
  become: true
  become_user: postgres
  command: psql -U bob image -c '\d image'

обратите внимание на параметры" become "и" become_user". Они скажут Ansible, чтобы перейти к правильному пользователю перед запуском команд.

важно: Ansible версии 1.9 и более раннее использование sudo: yes и sudo_user: postgres вместо become: true и become_user: postgres


основываясь на превосходных ответах выше, вы также можете указать переменные среды в своей задаче Ansible, как показано ниже. Обратите внимание, что это предполагает, что вы создали .файл pgpass с паролем для целевой БД.

-   name: Execute some sql via psql
    command: psql -f /path/to/your/sql
    environment:
        PGUSER: "{{ db_user }}"
        PGDATABASE: "{{ db_name }}"
        PGHOST: "{{ db_host }}"
        PGPASS: "{{ pgpass_filepath }}"