---
- name : Fail if Postgres not enabled
ansible.builtin.fail :
msg : "Postgres via the matrix-postgres role is not enabled (`matrix_postgres_enabled`). Cannot migrate."
when : "not matrix_postgres_enabled|bool"
- name : Fail if util called incorrectly (missing matrix_postgres_db_migration_request)
ansible.builtin.fail :
msg : "The `matrix_postgres_db_migration_request` variable needs to be provided to this util."
when : "matrix_postgres_db_migration_request is not defined"
- name : Fail if util called incorrectly (invalid matrix_postgres_db_migration_request)
ansible.builtin.fail :
msg : "The `matrix_postgres_db_migration_request` variable needs to contain `{{ item }}`."
with_items :
- src
- dst
- caller
- engine_variable_name
- systemd_services_to_stop
when : "item not in matrix_postgres_db_migration_request"
- name : Check if the provided source database file exists
stat :
path : "{{ matrix_postgres_db_migration_request.src }}"
register : matrix_postgres_db_migration_request_src_stat_result
- name : Fail if provided source database file doesn't exist
ansible.builtin.fail :
msg : "File cannot be found on the server at {{ matrix_postgres_db_migration_request.src }}"
when : "not matrix_postgres_db_migration_request_src_stat_result.stat.exists"
- block :
- name : Ensure pgloader repository is present on self-build
ansible.builtin.git :
repo : "{{ matrix_postgres_pgloader_container_image_self_build_repo }}"
dest : "{{ matrix_postgres_pgloader_container_image_self_build_src_path }}"
version : "{{ matrix_postgres_pgloader_container_image_self_build_repo_branch }}"
force : "yes"
become : true
become_user : "{{ matrix_user_username }}"
register : matrix_postgres_pgloader_git_pull_results
# If `stable` is used, we hit an error when processing /opt/src/pgloader/build/quicklisp/dists/quicklisp/software/uax-15-20201220-git/data/CompositionExclusions.txt:
# > the octet sequence #(194) cannot be decoded
#
# The issue is described here and is not getting fixed for months: https://github.com/dimitri/pgloader/pull/1179
#
# Although we're not using the dimitri/pgloader image, the one we're using suffers from the same problem.
- name : Switch pgloader base image from Debian stable (likely 10.x/Buster) to Bullseye
ansible.builtin.lineinfile :
path : "{{ matrix_postgres_pgloader_container_image_self_build_src_path }}/Dockerfile"
regexp : "{{ item.match }}"
line : "{{ item.replace }}"
with_items :
- match : '^FROM debian:stable-slim as builder$'
replace : 'FROM debian:bullseye-slim as builder'
- match : '^FROM debian:stable-slim$'
replace : 'FROM debian:bullseye-slim'
- name : Ensure pgloader Docker image is built
docker_image :
name : "{{ matrix_postgres_pgloader_docker_image }}"
source : build
force_source : "{{ matrix_postgres_pgloader_git_pull_results.changed if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}"
force : "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_postgres_pgloader_git_pull_results.changed }}"
build :
dockerfile : Dockerfile
path : "{{ matrix_postgres_pgloader_container_image_self_build_src_path }}"
pull : true
when : "matrix_postgres_pgloader_container_image_self_build|bool"
- name : Ensure pgloader Docker image is pulled
docker_image :
name : "{{ matrix_postgres_pgloader_docker_image }}"
source : "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}"
force_source : "{{ matrix_postgres_pgloader_docker_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}"
force : "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_postgres_pgloader_docker_image_force_pull }}"
when : "not matrix_postgres_pgloader_container_image_self_build"
# Defaults
- name : Set postgres_start_wait_time, if not provided
ansible.builtin.set_fact :
postgres_start_wait_time : 15
when : "postgres_start_wait_time|default('') == ''"
# Actual import work
# matrix-postgres is most likely started already
- name : Ensure matrix-postgres is started
ansible.builtin.service :
name : matrix-postgres
state : started
daemon_reload : true
register : matrix_postgres_service_start_result
- name : Wait a bit, so that Postgres can start
wait_for :
timeout : "{{ postgres_start_wait_time }}"
delegate_to : 127.0 .0 .1
become : false
when : "matrix_postgres_service_start_result.changed|bool"
# We only stop services here, leaving it to the caller to start them later.
#
# We can't start them, because they probably need to be reconfigured too (changing the configuration from using SQLite to Postgres, etc.),
# before starting.
#
# Since the caller will be starting them, it might make sense to leave stopping to it as well.
# However, we don't do it, because it's simpler having it here, and it also gets to happen only if we'll be doing an import.
# If we bailed out (somewhere above), nothing would have gotten stopped. It's nice to leave this running in such cases.
- name : Ensure systemd services blocking the database import are stopped
ansible.builtin.service :
name : "{{ item }}"
state : stopped
failed_when : false
with_items : "{{ matrix_postgres_db_migration_request.systemd_services_to_stop }}"
- name : Import {{ matrix_postgres_db_migration_request.engine_old }} database from {{ matrix_postgres_db_migration_request.src }} into Postgres
ansible.builtin.command :
cmd : >-
{{ matrix_host_command_docker }} run
--rm
--user={{ matrix_user_uid }}:{{ matrix_user_gid }}
--cap-drop=ALL
--network={{ matrix_docker_network }}
--mount type=bind,src={{ matrix_postgres_db_migration_request.src }},dst=/in.db,ro
--entrypoint=/bin/sh
{{ matrix_postgres_pgloader_docker_image }}
-c
'pgloader {{ matrix_postgres_db_migration_request.pgloader_options|default([])|join(' ') }} /in.db {{ matrix_postgres_db_migration_request.dst }}'
- block :
# We can't use `{{ role_path }}` here, neither with `import_tasks`, nor with `include_tasks`,
# because it refers to the role that included this util, and not to the role this file belongs to.
- import_tasks : "{{ role_path }}/../matrix-postgres/tasks/util/detect_existing_postgres_version.yml"
- ansible.builtin.set_fact :
matrix_postgres_docker_image_to_use : "{{ matrix_postgres_docker_image_latest if matrix_postgres_detected_version_corresponding_docker_image == '' else matrix_postgres_detected_version_corresponding_docker_image }}"
- name : Execute additional Postgres SQL migration statements
ansible.builtin.command :
cmd : >-
{{ matrix_host_command_docker }} run
--rm
--user={{ matrix_user_uid }}:{{ matrix_user_gid }}
--cap-drop=ALL
--env-file={{ matrix_postgres_base_path }}/env-postgres-psql
--network={{ matrix_docker_network }}
{{ matrix_postgres_docker_image_to_use }}
psql --host=matrix-postgres --dbname={{ matrix_postgres_db_migration_request.additional_psql_statements_db_name }} --command='{{ item }}'
with_items : "{{ matrix_postgres_db_migration_request.additional_psql_statements_list }}"
when : "matrix_postgres_db_migration_request.additional_psql_statements_list|default([])|length > 0"
- name : Archive {{ matrix_postgres_db_migration_request.engine_old }} database ({{ matrix_postgres_db_migration_request.src }} -> {{ matrix_postgres_db_migration_request.src }}.backup)
ansible.builtin.command :
cmd : "mv {{ matrix_postgres_db_migration_request.src }} {{ matrix_postgres_db_migration_request.src }}.backup"
- name : Inject result
ansible.builtin.set_fact :
matrix_playbook_runtime_results : |
{{
matrix_playbook_runtime_results|default([])
+
[
"NOTE: Your {{ matrix_postgres_db_migration_request.engine_old }} database file has been imported into Postgres. The original database file has been moved from `{{ matrix_postgres_db_migration_request.src }}` to `{{ matrix_postgres_db_migration_request.src }}.backup`. When you've confirmed that the import went well and everything works, you should be able to safely delete this file."
]
}}