Запустите скрипт 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 }}"